Swiftではこのようなパターンを時々使いました。
DispatchQueue.global().async {
// do stuff in background, concurrent thread
DispatchQueue.main.sync {
// update UI
}
}
このパターンの目的は明らかです。グローバルスレッドで時間のかかる計算を実行して、UIがロックされないようにし、計算が完了した後にメインスレッドでUIを更新します。
計算するものが何もない場合はどうなりますか?私のプロジェクトでロジックを見つけました
//A
DispatchQueue.main.sync {
// do something
}
クラッシュするが
// B
DispatchQueue.global().async {
DispatchQueue.main.sync {
// do something
}
}
クラッシュしません。
それらはどう違いますか?そして、ケース[〜#〜] b [〜#〜]はこれだけで異なりますか?
// C
DispatchQueue.main.async {
// do something
}
そしてもう一つ質問。メインスレッドがシリアルキューであることはわかっていますが、複数のコードブロックを複数のmain.async
、並行キューのように機能します。
DispatchQueue.main.async {
// do A
}
DispatchQueue.main.async {
// do B
}
メインスレッドが実際にシリアルキューである場合、どのようにして同時に実行できますか?メインスレッドがUIを更新できる以外に、グローバルコンカレントキューとどのように異なるのか、それが単なる時間スライスである場合はどうなりますか?
x.sync
は、呼び出しブロックが一時停止し、同期ブロックが続行するまで終了するまで待機することを意味します。だからあなたの例では:
DispatchQueue.global().async {
// yada yada something
DispatchQueue.main.sync {
// update UI
}
// this will happen only after 'update UI' has finished executing
}
通常、メインにsync
を戻す必要はありません。おそらく、非同期はデッドロックを回避するのに十分で安全です。非同期タスクを続行する前に、メインで何かが終了するまで待つ必要がある特別な場合を除きます。
クラッシュの例のように-同期の呼び出しと現在のキューのターゲット設定はデッドロックです(呼び出しキューは同期ブロックが完了するのを待ちますが、ターゲットキュー(同じ)がsync
の呼び出しを待ってビジー状態であるため開始しません仕上げ)そしてそれがおそらくクラッシュの理由です。
非同期でメインキューの複数のブロックをスケジュールする場合について:それらは並列に実行されません-それらは次々に発生します。また、キュー==スレッドであると想定しないでください。複数のブロックを同じキューにスケジュールすると、システムが許す限り多くのスレッドが作成される可能性があります。メインキューだけが特別で、メインスレッドを利用します。
キュー[もっと]
GCDには、主に3つのタイプのキューがあります。
1。メインキュー:はメインスレッドで実行され、シリアルキューです。
2。グローバルキュー:システム全体で共有される同時キュー優先度の異なる4つのキューがあります。高、デフォルト、低、バックグラウンドです。バックグラウンドプライオリティキューは最低のプライオリティを持ち、システムへの悪影響を最小限に抑えるために、あらゆるI/Oアクティビティで抑制されます。
3。カスタムキュー:シリアルまたは同時のユーザーが作成するキュー。これらのキュー内の要求は、実際にはグローバルキューの1つになります。
同期vs非同期
GCDでは、synchronously
またはasynchronously
のいずれかでタスクをディスパッチできます。
synchronous
関数は、タスクの完了後に呼び出し元に制御を返します。キューをブロックブロックし、タスクが完了するまで待機します。 DispatchQueue.sync(execute:)
を呼び出すことにより、作業単位を同期的にスケジュールできます。
asynchronous
関数はすぐに戻り、タスクの開始を命令しますが、タスクの完了を待機しません。したがって、非同期関数は、現在の実行スレッドが次の関数に進むのを妨げません。 DispatchQueue.async(execute:)
を呼び出すことにより、作業単位を非同期にスケジュールできます。
まとめ
一般に、現在のスレッドをブロックせずにネットワークベースのタスクまたはCPUを集中的に使用するタスクをバックグラウンドで実行する必要がある場合は、async
を使用します。
さまざまなキューをasync
でいつどのように使用するかについてのクイックガイドを次に示します。
async
を呼び出すと、現在のメソッドが終了した後、この新しいタスクが実行されることが保証されます。sync
の使用を検討する必要があることに注意してください。よくある間違い:
main
キューからDispatchQueue.main.sync
を呼び出すと、ディスパッチされたブロックが完了するまでキュー(main
)が待機するため、アプリはフリーズしますが、ディスパッチされたブロック)開始することさえできません(main
キューが停止して待機していたため)
ソースは here です