任意のスレッドからのコールバックがあります。このコールバックを受け取ったら、メインスレッドで特定のタスクを実行したいと思います。
私がすでにメインスレッドにいるかどうかを確認する必要がありますか?または、以下のコードを呼び出す前にこのチェックを実行しないことによるペナルティはありますか?
dispatch_async(dispatch_get_main_queue(), ^{
// do work here
});
任意のスレッドからのコールバックがあります。このコールバックを受け取ったら、メインスレッドで特定のタスクを実行したいと思います。
私がすでにメインスレッドにいるかどうかを確認する必要がありますか?または、以下のコードを呼び出す前にこのチェックを実行しないことによるペナルティはありますか?
dispatch_async(dispatch_get_main_queue(), ^{
// do work here
});
回答:
いいえ、すでにメインスレッドにいるかどうかを確認する必要はありません。ブロックをメインキューにディスパッチすることで、対応する実行ループが実行されるときに発生する、メインスレッドでシリアルに実行されるようにブロックをスケジュールするだけです。
すでにメインスレッドにいる場合、動作は同じです。ブロックがスケジュールされ、メインスレッドの実行ループが実行されるときに実行されます。
async
すると、実行されますが、アクションの予想されるタイミングが台無しになる可能性があります。このようにUIコードとしてviewDidLoad()
まで実行していない後のビューが最初に表示されます。
上で説明した非同期ディスパッチの場合、メインスレッドにいるかどうかを確認する必要はありません。Bavariousが示すように、これは単にメインスレッドで実行するためにキューに入れられます。
ただし、a dispatch_sync()
を使用して上記を実行しようとし、コールバックがメインスレッド上にある場合、アプリケーションはその時点でデッドロックになります。ここで私の回答でこれについて説明します。これは、コードを移動したときにこの動作に驚いたため-performSelectorOnMainThread:
です。そこで言及したように、ヘルパー関数を作成しました。
void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
あなたがいるメソッドが現在メインスレッド上にない場合、メインスレッド上でブロックを同期的に実行し、ブロックしている場合はインラインでブロックを実行します。これを使用するには、次のような構文を使用できます。
runOnMainQueueWithoutDeadlocking(^{
//Do stuff
});
dispatch_set_specific()
あなたが説明する場合に役立つでしょうか:stackoverflow.com/a/12806754/19679。
他の回答が述べたように、メインスレッドからのdispatch_asyncは問題ありません。
ただし、ユースケースによっては、デメリットを考慮する可能性のある副作用があります。ブロックはキューにスケジュールされているため、制御が実行ループに戻るまで実行されず、遅延の影響があります。ブロックの実行。
例えば、
NSLog(@"before dispatch async");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"inside dispatch async block main thread from main thread");
});
NSLog(@"after dispatch async");
印刷されます:
before dispatch async
after dispatch async
inside dispatch async block main thread from main thread
このため、外側のNSLogの間でブロックが実行されることを期待している場合、dispatch_asyncは役に立ちません。
いいえ、メインスレッドにいるかどうかを確認する必要はありません。これはSwiftでこれを行う方法です:
runThisInMainThread { () -> Void in
runThisInMainThread { () -> Void in
// No problem
}
}
func runThisInMainThread(block: dispatch_block_t) {
dispatch_async(dispatch_get_main_queue(), block)
}
それは私のリポジトリの標準関数として含まれています、それをチェックしてください:https : //github.com/goktugyil/EZSwiftExtensions