7
{
    dispatch_queue_t myQueue = dispatch_queue_create("com.mycompany.myqueue", 0);

    dispatch_sync(myQueue, ^{

        //Do EXTREME PROCESSING!!!
        for (int i = 0; i< 100; i++) {
            [NSThread sleepForTimeInterval:.05];
            NSLog(@"%i", i);
        }

        dispatch_sync(dispatch_get_main_queue(), ^{
            [self updateLabelWhenBackgroundDone];
        });
    });
}

ここでデッドロックが発生しています。アップルのドキュメントによると

"dispatch_sync": "同期実行のためにブロックをディスパッチ キューに送信します。dispatch_async とは異なり、この関数はブロックが完了するまで戻りません。この関数を呼び出して現在のキューをターゲットにすると、デッドロックが発生します。".

ただし、外側dispatch_syncをオンにしてから、別のキュー「main_queue」でmyQueue内側を実行します。ditpatch_sync

デッドロックの理由を見つけることができません。ここでコメント/ヘルプをいただければ幸いです。

4

3 に答える 3

12

そのように myQueue に dispatch_sync を送信し、呼び出しがメイン スレッドで発生した場合、dispatch_sync は可能であれば、dispatch_async のように新しいワーカー スレッドではなく、その場でブロックを実行します。キューに個別のワーカー スレッドを取得できる保証はありません。

その後、ブロックは 2 回目の dispatch_sync 呼び出しに到達するまでメイン スレッドで実行されます。この呼び出しはたまたまメイン キューをターゲットにしています。そのキューには既にブロックが実行されているため、サービスを提供できず、そこでデッドロックが発生します。

それが問題である場合、つまり、最初の dispatch_sync が実際にメイン スレッドから来ている場合は、dispatch_async に切り替える必要があります。長時間実行される「EXTREME PROCESSING」操作でメインスレッドをブロックしたくないでしょう。

于 2013-08-18T08:38:28.053 に答える
7

dispatch_syncあなたは2回電話しています。初回は、ブロックが完了するのを待ってメイン スレッドを一時停止します。次にブロックは、メイン スレッドにプッシュ バックしようとする 2 番目の呼び出しでバックグラウンド スレッドを中断します (ブロックは中断されているため、キューからブロックを処理することはありません)。両方のスレッドが互いに待機しています。

呼び出しの少なくとも 1 つが である必要がありますdispatch_async

于 2013-08-18T08:36:08.553 に答える
2

同様の問題があり、これらの解決策はどれも機能しませんでした。自分より頭のいい人に聞いた。

私の問題は、非同期ワーカー ブロックのディスパッチを生成してから、進行状況ウィンドウを表示していたことです。経由でメインスレッドにコールバックします

dispatch_sync(dispatch_get_main_queue(), ^{})

非同期呼び出しと同様に失敗しました。

説明は、モーダル ウィンドウが原因で、メイン スレッドが「コモンズ モード」ではなくなったというものでした。メインスレッドへの呼び出しをこれに置き換えました....

CFRunLoopPerformBlock(([[NSRunLoop mainRunLoop] getCFRunLoop]), (__bridge CFStringRef)NSModalPanelRunLoopMode, ^{
        //Update UI thread.

    });
于 2014-08-19T23:46:18.310 に答える