1. ホーム
  2. ios

[解決済み] dispatch_async(dispatch_get_main_queue(), ^{...}); は完了するまで待つのですか?

2022-02-16 19:56:15

質問

私のアプリでは、データ処理とUI更新からなる時間のかかる作業をメソッドで行いたいシナリオがあります。私のメソッドは次のようなものです。

- (void)doCalculationsAndUpdateUIs {

    // DATA PROCESSING 1
    // UI UPDATE 1

    // DATA PROCESSING 2
    // UI UPDATE 2

    // DATA PROCESSING 3
    // UI UPDATE 3
} 

時間がかかるので、バックグラウンドスレッドでデータ処理を行いたいと思い、使ってみました。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{

しかし、データ処理とUI更新が同じメソッドで行われているため、UI更新のみをメインスレッドで行いたいと考えました。

dispatch_async(dispatch_get_main_queue(), ^{

最後に私のメソッドは次のようになります。

- (void)doCalculationsAndUpdateUIs {

    // DATA PROCESSING 1 
    dispatch_async(dispatch_get_main_queue(), ^{
        // UI UPDATE 1
    });

    /* I expect the control to come here after UI UPDATE 1 */

    // DATA PROCESSING 2
    dispatch_async(dispatch_get_main_queue(), ^{
        // UI UPDATE 2
    });

    /* I expect the control to come here after UI UPDATE 2 */

    // DATA PROCESSING 3
    dispatch_async(dispatch_get_main_queue(), ^{
        // UI UPDATE 3
    });
}

これは本当に効果があるのだろうか?これは本当に良い方法なのでしょうか?これを実現するための最良の方法は何でしょうか?

追伸:この3つの作業は、すべて互いに関連しています。


EDITです。 みんな、ごめんね。私は 上記のコードに一行抜けがありました . 私の実際のコードは以下のようなものです。

- (void)doCalculationsAndUpdateUIs {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // DATA PROCESSING 1 
        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATE 1
        });

        /* I expect the control to come here after UI UPDATE 1 */

        // DATA PROCESSING 2
        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATE 2
        });

        /* I expect the control to come here after UI UPDATE 2 */

        // DATA PROCESSING 3
        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATE 3
        });
    });
}

改めて、混乱させてしまったことを本当に申し訳なく思います。

解決方法は?

そのサンプルでやっている方法は良いやり方ではありません。

dispatch_async は常に 非同期 . これは、すべてのUIブロックを同じキューにエンキューしているため、異なるブロックが順番に実行されますが、データ処理コードと並行して実行されるだけなのです。

更新を待たせたい場合は dispatch_sync の代わりに

// This will wait to finish
dispatch_sync(dispatch_get_main_queue(), ^{
    // Update the UI on the main thread.
});

もう一つのアプローチは、ブロックをネストエンキューすることです。I はしないでしょう。 しかし、多段階ではお勧めできません。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Background work

    dispatch_async(dispatch_get_main_queue(), ^{
        // Update UI

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // Background work

            dispatch_async(dispatch_get_main_queue(), ^{
                // Update UI
            });
        });
    });
});

UIの更新を待つ必要がある場合は、同期バージョンを使用する必要があります。バックグラウンドスレッドがメインスレッドを待っていても、まったく問題ありません。UIの更新は非常に速いはずです。