10

dispatch_syncを使用してブロックを実行していますが、ブロックは正しく実行されています。ただし、このブロックはメインスレッドで実行されます。Apple Docによると:

シリアルキュー(プライベートディスパッチキューとも呼ばれます)は、キューに追加された順序で一度に1つのタスクを実行します。現在実行中のタスクは、ディスパッチキューによって管理される個別のスレッド(タスクごとに異なる可能性があります)で実行されます。

これは、実行されている現在のプロセスが別のスレッドで実行されることを意味します(または私が理解したこと)。

以下は、何が起こっているのかを判断するために使用しているコードです。NSURLConnectionのdidReceiveData:デリゲートメソッド内で呼び出されています(didReceiveData:デリゲートメソッド内でこれを行うべきではないことはわかっていますが、これはdispatch_syncに焦点を当てたサンプルにすぎません)。以下は、私の結論の証拠として私が想定できるさまざまな方法です。

  1. グローバル並行キューでのdispatch_syncの使用

       dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            if ([NSThread isMainThread]) {
                NSLog(@"Main Thread");
            }
            else
                NSLog(@"Not on Main Thread");
    
            //Some Process
        });
    

出力-

         Main Thread
         Main Thread 
         Main Thread
         // Main Thread printed till didReceiveData: gets called

  1. dispatch_queue_createを使用して自己作成キューでdispatch_syncを使用する

    // Create queue somewhere else like this
    dispatch_queue_t newQueue = dispatch_queue_create("WriteQueue", DISPATCH_QUEUE_SERIAL);
    
    
       dispatch_sync(newQueue, ^{
    
            if ([NSThread isMainThread]) {
                NSLog(@"Main Thread");
            }
            else
                NSLog(@"Not on Main Thread");
    
            //Some Process
        });
    

出力-

         Main Thread
         Main Thread 
         Main Thread
         // Main Thread printed till didReceiveData: gets called

ここで少し驚いています。ブロックは常にメインスレッドで実行されるか、何かが足りません。Apple Docに反しているように見えるので、そう思います。誰かがこれが何であるか知っていますか?

更新:他の議論と同様に、dispatch_syncが同じスレッドでブロックを実行することを理解しています(ほとんどの場合)。それでは、なぜアップルドキュメントのステートメントがいくつかの点で矛盾しているのですか。アップルが「現在実行中のタスクは、ディスパッチキューによって管理される別のスレッド(タスクごとに異なる可能性があります)で実行される」と言う理由。それとも私はまだ何かが足りないのですか?

4

4 に答える 4

15

dispatch_sync()は同じスレッドにブロックをディスパッチしますが、これは正常です。

編集

Appleのドキュメントには、これだけでなく、次のようにも書かれています。

最適化として、この関数は可能な場合は現在のスレッドのブロックを呼び出します。

補足として(同期バージョンについて話していることは知っていますが、これを正確に説明しましょう)また、dispatch_async()によって、同じスレッドで複数のブロックが実行される可能性があります。

于 2012-12-20T12:20:37.423 に答える
5

背景ブロックには、

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // background code
});

_syncではなく_asyncであることに注意してください

編集:同様に、メインスレッドで何かを実行するには、

dispatch_async(dispatch_get_main_queue(), ^{
    // main thread code
});
于 2012-12-20T12:20:59.680 に答える
4

Grand Central Dispatchは、メインキューに送信されたブロックがメインスレッドで実行されることを保証できますが、他のキューに送信されたブロックは、ブロックがどのスレッドで実行されるかについて保証されないことを理解することが重要です。

ブロックが呼び出されるスレッドについては保証されません。ただし、FIFOディスパッチキューに送信された1つのブロックのみが一度に呼び出されることが保証されています。

Grand Central Dispatchはスレッドのプールを管理し、既存のスレッドを可能な限り再利用します。メインスレッドが作業に使用できる場合(つまりアイドル状態の場合)、そのスレッドでブロックを実行できます。

于 2014-08-14T01:41:45.503 に答える
0

Swiftでこれを行う方法は次のとおりです。

runThisInMainThread { () -> Void in
    // Runs in the main thread
}

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

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

于 2015-12-06T03:34:33.527 に答える