2013-07-11 14 views
9

NSURLConnectionを使用して非同期Webリクエストを使用するアプリケーションをプログラミングしているので、複数のスレッドが実行されています。私のアプリケーションの主なロジックが1つのスレッドで行われるように、私はperformSelectorOnMainThread:waitUntilDone:を大量に使用しています。時には、私はこれをメインスレッドで実行しています。これが私の好奇心を刺激しました。performSelectorOnMainThread:waitUntilDone:がメインスレッドから呼び出されたとき、いつ実行されますか?

メインスレッド中にperformSelectorOnMainThread:waitUntilDone:が呼び出された場合は、 performSelector:と同じように動作しますか? waitUntilDone:YESの場合はどうなりますか? NOの場合はどうなりますか?

編集:私はwaitUntilDone:YESあるとき、セレクタが(ほぼ)即座に実行されますが、waitUntilDone:NOであれば、それが実行されたとき、私は理解できないことを見出しました。

+0

'waitUntilDone:'が 'YES'のとき、セレクタは直ちに(ほぼ)実行されますが、' waitUntilDone: 'が' NO'のときにいつ実行されるのか分かりません。 – Jumhyn

+0

デバッガーはここでは役に立ちませんか?新しいスレッドがいつ生成されるかを調べるだけです。 –

+0

@Cole、 'performSelector' ** OnMainThread:**は、特にスレッドからメインスレッドと呼ばれるときにスレッドを作成しません。 –

答えて

13
performSelectorOnMainThread:withObject:waitUntilDone: 

はあなたのapplicationmain threadにメッセージを配信する方法です。ここではbooleanの値waitUntilDone:の値は、を実行するかどうかをブロックselectorでブロックするかどうかを指定します。例えば

-

あなたはこれらの2

lines-
[self performSelectorOnMainThread:@selector(print) withObject:nil waitUntilDone:YES]; 

NSLog(@"Hello iPhone"); 

を書かれており、これは、印刷法である場合 -

- (void) print 
{ 
    NSLog(@"Hello World"); 
} 

、あなたは、このO/P

を取得します
Hello World 
Hello iPhone 

だからこそtはあなたのmain threadと印刷の「Hello World」の実行を一時停止し、あなたがwaitUntilDone:

YESを指定したため、再度メインスレッドを実行し、印刷の「Hello iPhone」が、あなたはwaitUntilDone:NOを指定した場合、それは次のように出力します -

Hello iPhone 
Hello World 

それは明らかにそれがqueueで指定されたselectorを実行するリクエストを入れて、OSがそのmain thread自由を取得するとして、それはあなたの要求を実行することを示しています。

main threadからかsecondary threadのいずれかperformSelectorOnMainThread:withObject:waitUntilDone:を呼び出すと、それの実行中に任意の違いはありません、それはあなたがより多くの情報のためwaitUntilDone:

に指定されたものに依存 -

NSObject Class Reference

+0

@saabdip +1すてきな説明です。 – iLearner

+1

私は確かにニックピッキングしていますが、あなたは間違っています。「あなたが 'NO'を指定すると、 'Hello iPhone \ nHelloWorld'」と表示されます。実際には、コールサイトがメインスレッド上で実行されていない場合、2つの出力の順序は決定できません。それ以外の場合、コールサイトがメインスレッド上で実行されると、メインスレッドはブロックされません。代わりに_waitUntilDone_が 'YES'の場合、セレクタは即座に実行されます。 ;)最後のステートメントはあまりにも曖昧です。 – CouchDeveloper

1
If the current thread is also the main thread, and you pass YES, 
the message is performed immediately, otherwise the perform is 
queued to run the next time through the run loop. 

はいの場合は、performSelectorOnMainThread:withObject:waitUntilDone:が返される前に実行できます。

私は、waitUntilDone:がYESの場合、セレクタはすぐに実行されますが、waitUntilDone:がNOの場合はいつ実行されるかわかりません。

実行ループに関するビット:メインスレッドには実行ループがあります。これにより、スレッドが終了するのを防ぐことができます。実行ループはToDoリストを管理します。その作業が完了すると、しばらくそのスレッドの実行を中断します。その後、それは後で目を覚まし、もしうまくいくかどうかを確かめます。

作業量は大きく異なる可能性があります(たとえば、目を覚ましてからセレクタが実行されるまでの間に、かなり重い図面やファイルの入出力が行われる可能性があります)それがどのように動作するかを知るために十分であるべきで、どのように実装が実行ループに作業を追加

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

1

waitUntilDone場合:YES、それは即時関数呼び出しとして機能している

waitUntilDone場合:NOの場合、他のすべてのスレッドの呼び出しとともに呼び出しをキューに入れます。

この方法は、一般的な実行ループの使用メインスレッド モード-、一定 NSRunLoopCommonModesに関連付けられたモードでの実行ループにメッセージをキューイングします。通常の実行ループ の処理の一部として、メインスレッドはメッセージをデキューし(一般的な実行ループモードのいずれかで実行する と仮定して)、目的の メソッドを呼び出します。

前述のように、描画やI/Oなどはキュー内のものよりも優先されます。メインスレッドが次のイベントループで待ち行列サービスに時間を割いた後は、先入れ先出しで数えるのと同じくらい簡単ではない他のいくつかの詳細があります:1)dispatch_async()ブロックはモードを無視します。

2)特定のモード引数を持つperformSelectorバリアント、たとえばイベントトラッキングは、特定のモードで実行されているループ内のデフォルトの共通モード引数よりも優先される可能性があります。

一般的なルールとして、予測可能なタイミング動作が必要な場合は、実行ループモードなどのより高いレベルの考慮事項を考慮しない低レベルのGCDディスパッチ機能を使用する必要があります。

関連する問題