web-dev-qa-db-ja.com

DispatchQueue.main.asyncとDispatchQueue.main.syncの違い

私は昔からDispatchQueue.main.asyncを使用してUI関連の操作を実行してきました。しかしSwiftはDispatchQueue.main.asyncとDispatchQueue.main.syncを提供しており、どちらもメインキューで実行されます。それで、だれでもそれらの違いを私に言うことができますか?そしていつ私はそれらを使うべきですか?前もって感謝します。

        DispatchQueue.main.async {
            self.imageView.image = imageView
            self.lbltitle.text = ""

        }
        DispatchQueue.main.sync {
            self.imageView.image = imageView
            self.lbltitle.text = ""

        }
61
Aman.Samghani

なぜ同時実行性があるのですか?データのロードなどの重いタスクをアプリに追加するとすぐに、UIの動作が遅くなったり、フリーズしたりします。並行性により、2つ以上のタスクを「同時に」実行できます。この方法の欠点は、スレッドの安全性であり、必ずしも制御が簡単ではないことです。 F.e.異なるスレッドで同じ変数を変更しようとしたり、異なるスレッドによってすでにブロックされているリソースにアクセスしたりするなど、さまざまなタスクが同じリソースにアクセスしたい場合。

注意する必要がある抽象化がいくつかあります。

  • キュー.
  • 同期/非同期タスクパフォ​​ーマンス.
  • 優先順位.
  • よくあるトラブル.

キュー

シリアルまたは同時である必要があります。グローバルグローバルまたはプライベートプライベートと同時に。

シリアルキューでは、タスクは1つずつ完了し、並行キューではタスクは同時に実行され、予期しないスケジュールで終了します。同じグループのタスクは、並行キューに比べてシリアルキューの方が時間がかかります。

あなたはあなた自身のプライベートキュー(両方シリアルまたは同時)を作成するか、すでに利用可能なグローバル(システム)キューを使用できます。 メインキューは、すべてのグローバルキューの中で唯一のシリアルキューです。

メインキュー(ネットワークからのデータのロード)では、UI作業と呼ばれないような重いタスクを実行しないことを強くお勧めします。代わりに、UIを凍結させないために他のキューで実行しますそしてユーザーの行動に反応する。他のキューでUIを変更すると、別の予期しないスケジュールと速度で変更が行われる可能性があります。いくつかのUI要素は、必要に応じて前後に描画できます。 UIがクラッシュする可能性があります。 global queuessystem queuesなので、それらによってシステムが実行できるタスクがいくつかあることにも留意する必要があります。


サービス品質/優先度

キューには異なるQoS(サービス品質)があり、タスクの実行優先度を設定します(ここで最高から最低まで):
。userInteractive - メインキュー
。userInitiated - ユーザーが何らかの応答を待つタスクを開始しました。
。utility - 時間がかかり、即時の対応を必要としないタスク、たとえばデータの処理
。background - 視覚的な部分とは無関係で、完了時間に厳密ではないタスク用です。

もあります

qos情報を転送しないデフォルトキュー。 qosを検出できなかった場合は、。userInitiated。utilityの間にqosが使用されます。

タスクは同期的に同期的にまたは非同期的に実行することができます

  • 同期関数は、タスクが終了した後にのみ現在のキューに制御を戻します。キューをブロックし、タスクが終了するまで待ちます。

  • 非同期関数は、タスクが送信された直後に別のキューで実行されるように現在のキューに制御を戻します。タスクが終了するまで待ちません。キューをブロックしません。

よくあるトラブル

コンカレントアプリを投影する際にプログラマが犯す最もよくある間違いは次のとおりです。

  • 競合状態 - アプリの動作がコード部分の実行順序に依存する場合に発生します。
  • 優先順位の逆転 - いくつかのリソースがブロックされているため、優先順位の高いタスクが優先順位の低いタスクの終了を待つ場合
  • デッドロック - いくつかのキューが、これらのキューのいくつかによって既にブロックされているソース(変数、データなど)を無限に待機している場合。

メインキューのsync関数を呼び出さないでください
メインキューでsync関数を呼び出すと、キューがブロックされるだけでなく、キューはタスクの完了を待機しますが、タスクは開始できないためタスクは終了しません。キューが原因ですでにブロックされています。それはデッドロックと呼ばれます。

いつsyncを使うのか?タスクが終了するまで待つ必要がある場合。 F.e.ある関数/メソッドが二重に呼び出されないようにしているとき。 F.e.同期が取れていて、完全に終了するまでそれが二重に呼び出されるのを防ごうとしています。これがこの懸念を表すコードです。
IOSデバイスでエラークラッシュレポートの原因を特定する方法?

117
Alexander

asyncを使用すると、ディスパッチされたブロックが実行されるまで待たずに呼び出しキューを続行できます。反対にsyncは呼び出しキューを停止させ、ブロック内でディスパッチした作業が完了するまで待機します。したがって、syncはデッドロックにつながる可能性があります。メインキューからDispatchQueue.main.syncを実行してみてください。呼び出し側のキューは、ディスパッチされたブロックが終了するまで待機しますが、起動できなくなります(キューが停止して待機しているため)。

syncを使用する場合DIFFERENTキューで何かが行われるのを待ち、それから現在のキューで作業を続ける必要があるとき

Syncの使用例

1つのスレッドだけが保護されたコードを同時に実行できるようにするために、シリアルキューではsyncをミューテックスとして使用できます。

20