これは 2 つの部分からなる質問です。誰かが完全な回答で返信できることを願っています。
NSOperation
は強力なオブジェクトです。これらは、非同時または同時の 2 つの異なるタイプにすることができます。
最初のタイプは同期的に実行されます。に追加することで、非同時操作を利用できますNSOperationQueue
。後者はスレッドを作成します。結果は、その操作を同時に実行することになります。唯一の注意点は、このような操作のライフサイクルに関するものです。そのmain
メソッドが終了すると、キューから削除されます。これは、非同期 API を扱う場合に問題になる可能性があります。
では、同時操作についてはどうでしょうか。アップルのドキュメントから
並行操作 (つまり、呼び出しスレッドに対して非同期で実行される操作) を実装する場合は、追加のコードを記述して、操作を非同期で開始する必要があります。たとえば、別のスレッドを生成したり、非同期システム関数を呼び出したり、その他のことを行って、start メソッドがタスクを開始し、すぐに、おそらくタスクが終了する前に戻るようにすることができます。
これは私にはほとんど明らかです。それらは非同期で実行されます。ただし、確実に実行できるように適切なアクションを実行する必要があります。
私には明らかでないことは、次のとおりです。Doc 言います:
注: OS X v10.6 では、操作キューは isConcurrent によって返された値を無視し、常に別のスレッドから操作の start メソッドを呼び出します。
それは本当にどういう意味ですか?に同時操作を追加するとどうなりNSOperationQueue
ますか?
次に、この投稿のConcurrent OperationsNSURLConnection
では、同時操作を使用して(非同期形式で) HTTP コンテンツをダウンロードします。操作は並行しており、特定のキューに含まれています。
UrlDownloaderOperation * operation = [UrlDownloaderOperation urlDownloaderWithUrlString:url];
[_queue addOperation:operation];
ループを実行する必要があるためNSURLConnection
、作成者はメインスレッドでメソッドをシャントしstart
ます (そのため、操作をキューに追加すると、別のスレッドが生成されると思います)。このようにして、メインの実行ループは、操作に含まれるデリゲートを呼び出すことができます。
- (void)start
{
if (![NSThread isMainThread])
{
[self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
return;
}
[self willChangeValueForKey:@"isExecuting"];
_isExecuting = YES;
[self didChangeValueForKey:@"isExecuting"];
NSURLRequest * request = [NSURLRequest requestWithURL:_url];
_connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
if (_connection == nil)
[self finish];
}
- (BOOL)isConcurrent
{
return YES;
}
// delegate method here...
私の質問は次のとおりです。このスレッドは安全ですか? 実行ループはソースをリッスンしますが、呼び出されたメソッドはバックグラウンド スレッドで呼び出されます。私が間違っている?
編集
Dave Dribin から提供されたコードに基づいて、自分でいくつかのテストを完了しました ( 1を参照)。あなたが書いたように、のコールバックがメインスレッドNSURLConnection
で呼び出されることに気付きました。
わかりましたが、今でも非常に混乱しています。私の疑問を説明しようと思います。
メインスレッドでコールバックが呼び出される非同期パターンを同時操作に含めるのはなぜですか? メソッドをメイン スレッドにシャントするstart
と、メイン スレッドでコールバックを実行できるようになります。また、キューと操作についてはどうでしょうか。GCD が提供するスレッド化メカニズムはどこで利用できますか?
これが明確であることを願っています。