146

私は自分のアプリで成功を収めてグランドセントラルディスパッチを使用してきましたが、次のようなものを使用することの本当の利点は何であるか疑問に思いました。

dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff

あるいは

dispatch_sync(dispatch_get_main_queue(), ^{ ... do stuff

つまり、どちらの場合も、アプリが実行されている場所でメインスレッドで実行されるブロックを起動しているため、負荷を軽減することはできません。最初のケースでは、ブロックがいつ実行されるかを制御できません。ブロックを発射してから0.5秒後にブロックが実行されるケースを見てきました。2番目のケースは、

[self doStuff];

右?

どう思いますか?

4

6 に答える 6

296

メインキューへのブロックのディスパッチは、通常、バックグラウンドキューから行われ、バックグラウンド処理が終了したことを通知します。

- (void)doCalculation
{
    //you can use any string instead "com.mycompany.myqueue"
    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);

    dispatch_async(backgroundQueue, ^{
        int result = <some really long calculation that takes seconds to complete>;

        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateMyUIWithResult:result];
        });    
    });
}

この場合、バックグラウンドキューで長い計算を行っているため、計算が完了したらUIを更新する必要があります。UIの更新は通常、メインキューから実行する必要があるため、2番目のネストされたdispatch_asyncを使用してメインキューに「シグナル」を返します。

メインキューにディスパッチして戻す例は他にもありますが、通常はこの方法で実行されます。つまり、バックグラウンドキューにディスパッチされたブロック内からネストされます。

  • バックグラウンド処理が終了しました->UIを更新します
  • バックグラウンドキューで処理されたデータのチャンク->メインキューに次のチャンクを開始するように通知
  • バックグラウンドキューの着信ネットワークデータ->メッセージが到着したことをメインキューに通知します
  • などなど

メインキューからメインキューにディスパッチする理由については...まあ、通常はそうしませんが、次回の実行ループで実行する作業をスケジュールするためにディスパッチすることも考えられます。

于 2011-10-26T16:06:42.420 に答える
17

メインスレッドからメインキューにブロックをディスパッチする便利です。これにより、メインキューに、キューに入れられた他のブロックを処理する機会が与えられるため、他のすべての実行を単純にブロックすることはありません。

たとえば、多くの同時接続を処理する、本質的にシングルスレッドのサーバーを作成できます。キュー内の個々のブロックに時間がかかりすぎない限り、サーバーは新しい要求に応答し続けます。

プログラムがイベントに対応するために一生を費やす以外に何もしない場合、これは非常に自然なことです。メインキューで実行するようにイベントハンドラーを設定してからdispatch_main()を呼び出すだけで、スレッドセーフについてまったく心配する必要がない場合があります。

于 2012-04-11T19:51:46.773 に答える
11

うまくいけば、dispatch_asyncとdispatch_syncの違いについて疑問に思っているという点で、あなたの質問を正しく理解していますか?

dispatch_async

ブロックを非同期でキューにディスパッチします。つまり、ブロックをキューに送信し、ブロックが戻るのを待たずに、メソッドの残りのコードの実行を続行します。

dispatch_sync

ブロックを同期的にキューにディスパッチします。これにより、ブロックの実行が終了するまで、メソッド内の残りのコードが実行されなくなります。

私は主dispatch_asyncにバックグラウンドキューを使用して、メインキューから作業を取り除き、デバイスにある可能性のある追加のコアを利用しました。次にdispatch_async、UIを更新する必要がある場合は、メインスレッドに移動します。

幸運を

于 2011-10-26T16:24:42.803 に答える
9

長い操作の前にスピナーを設定するなど、UIアクティビティに役立つ場所の1つは次のとおりです。

- (void) handleDoSomethingButton{

    [mySpinner startAnimating];

    (do something lengthy)
    [mySpinner stopAnimating];
}

長い間メインスレッドをブロックし、UIKitに実際にスピナーを起動させないため、機能しません。

- (void) handleDoSomethingButton{
     [mySpinner startAnimating];

     dispatch_async (dispatch_get_main_queue(), ^{
          (do something lengthy)
          [mySpinner stopAnimating];
    });
}

制御を実行ループに戻します。これにより、UIの更新がスケジュールされ、スピナーが開始され、次にディスパッチキューから次のものが取得されます。これが実際の処理です。処理が完了すると、アニメーションストップが呼び出され、実行ループに戻ります。ここで、UIがストップで更新されます。

于 2014-07-10T02:48:11.743 に答える
8

スウィフト3、4、5

メインスレッドでコードを実行する

DispatchQueue.main.async {
    // Your code here
}
于 2018-02-16T12:23:56.173 に答える
1

非同期とは非同期を意味し、ほとんどの場合それを使用する必要があります。タスクが完了するまでUIがロックされるため、メインスレッドでsyncを呼び出さないでください。Swiftでこれを行うためのより良い方法は次のとおりです。

runThisInMainThread { () -> Void in
    // Run your code like this:
    self.doStuff()
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

それは私のリポジトリに標準機能として含まれています、それをチェックしてください:https ://github.com/goktugyil/EZSwiftExtensions

于 2015-12-06T03:44:53.980 に答える