web-dev-qa-db-ja.com

Dispatch_asyncについて

このコードについて質問があります

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSData* data = [NSData dataWithContentsOfURL: 
      kLatestKivaLoansURL];
    [self performSelectorOnMainThread:@selector(fetchedData:) 
      withObject:data waitUntilDone:YES];
});

このコードの最初のパラメータは

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

このコードは、その定義自体が特定の優先順位レベルのグローバル並行キューを返すというグローバルキューでシリアルタスクを実行するように求めていますか?

メインキューよりもdispatch_get_global_queueを使用する利点は何ですか?

私は混乱しています。私がこれをよりよく理解するのを手伝ってください。

223
user2332873

メインキューではなくデフォルトキューを使用する主な理由は、バックグラウンドでタスクを実行することです。

たとえば、インターネットからファイルをダウンロードしていて、ダウンロードの進行状況についてユーザーを更新したい場合は、優先順位のデフォルトキューでダウンロードを実行し、メインキューのUIを非同期的に更新します。

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
    });
});
494
David

すべてのDISPATCH_QUEUE_PRIORITY_Xキューは並行キュー(一度に複数のタスクを実行できることを意味します)で、特定のキュー内のタスクが "先入れ先出し"の順序で実行を開始するという意味でFIFOです。これはシリアルキューである(dispatch_get_main_queue()からの)メインキューと比較したものです(タスクは受け取った順に実行を開始し、実行を終了します)。

したがって、1000個のdispatch_async()ブロックをDISPATCH_QUEUE_PRIORITY_DEFAULTに送信した場合、それらのタスクはキューに送信した順序で実行を開始します。 HIGH、LOW、およびBackgroundキューの場合も同様です。これらのキューに送信したものはすべて、メインアプリケーションスレッドとは別の代替スレッドでバックグラウンドで実行されます。したがって、これらのキューはバックグラウンドダウンロード、圧縮、計算などのタスクを実行するのに適しています。

実行順序は、キューごとにFIFOです。したがって、1000個のdispatch_async()タスクを4つの異なる同時キューに送信し、それらを均等にバックグラウンド、LOW、DEFAULT、およびHIGHに分割して送信する(つまり、HIGHキューで最後の250タスクをスケジュールする)これらのタスクはできるだけ早くCPUに到達する必要があるとシステムが判断したので、最初に表示されるタスクはそのHIGHキューにあります。

また、私は「順番に実行を開始する」と言っていますが、並行キューとして、各タスクの時間の長さに応じて順番に実行が終了するとは限らないことに注意してください。

アップルによると:

https://developer.Apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

並行ディスパッチキューは、並行して実行できる複数のタスクがある場合に役立ちます。並行キューは、先入れ先出しの順序でタスクをデキューするという点で、依然としてキューです。ただし、以前のタスクが終了する前に、並行キューが追加のタスクをデキューする可能性があります。特定の瞬間に並行キューによって実行されるタスクの実際の数は可変であり、アプリケーション内の条件が変わると動的に変わる可能性があります。利用可能なコアの数、他のプロセスによって行われている作業量、他のシリアルディスパッチキュー内のタスクの数と優先順位など、多くの要因が並行キューによって実行されるタスクの数に影響します。

基本的に、1000個のdispatch_async()ブロックをDEFAULT、HIGH、LOW、またはbackgroundsキューに送信すると、それらはすべて送信順に実行を開始します。ただし、短いタスクは長いタスクよりも先に終了することがあります。これの理由は、利用可能なCPUコアがあるか、または現在のキュータスクが計算的に非集中的な作業を実行しているか(したがって、コア数に関係なく追加タスクを並行してディスパッチできるとシステムに判断させる)です。

並行性のレベルは完全にシステムによって処理され、システム負荷およびその他の内部的に決定された要因に基づきます。これがGrand Central Dispatch(dispatch_async()システム)の長所です - あなたは単にあなたのワークユニットをコードブロックとして作り、それらに(あなたが選んだキューに基づいて)優先順位を設定しそしてシステムに残りを処理させます。

だからあなたの上記の質問に答えるために:あなたは部分的に正しいです。指定された優先順位レベルでグローバル並行キューで並行タスクを実行するように「そのコードに依頼」しています。ブロック内のコードはバックグラウンドで実行され、追加の(類似の)コードはシステムの利用可能なリソースの評価に応じて潜在的に並列に実行されます。

一方、(dispatch_get_main_queue()からの)「メイン」キューはシリアルキューです(同時ではありません)。メインキューに送信されたタスクは常に順番に実行され、順番に終了します。これらのタスクはUIスレッドでも実行されるため、進捗メッセージ、完了通知などでUIを更新するのに適しています。

194
SimplePanda

スイフト版

これはDavidのObjective-Cの答えのSwift版です。バックグラウンドで物事を実行するにはグローバルキュー、UIを更新するにはメインキューを使用します。

スイフト3

DispatchQueue.global(qos: .background).async {

    // Background Thread

    DispatchQueue.main.async {
        // Run UI Updates
    }
}
29
Suragch