5

はい、知っています。世界についてはたくさんの質問と回答がありますNSOperationが、私はまだいくつかの疑問を持っています。Il'は、2つの部分からなる質問で私の疑問を説明しようとします。それらは互いに関連しています。

SO post nsoperationqueue-and-concurrent-vs-non-concurrentで、Darrenは次のように書いています。

「並行」操作は、それ自体が並行です。スレッドを作成するためにNSOperationQueueは必要ありません。

しかし、少し調べてみるとNSOperation、同時宣言されていても(isConcurrentreturnsなどのメソッドをオーバーライドするYESことで)、に追加できることがわかりましたNSOperationQueue。これは何を意味するのでしょうか?コンカレントNSOperationをキューに追加すると、内部で何が起こっているのでしょうか。逆に、(キューに追加せずに)並行操作をそのまま使用するとどうなりますか?

Appleのドキュメントから取ったメモは明確です:

...操作キューはisConcurrentによって返される値を無視し、常に別のスレッドから操作のstartメソッドを呼び出します。...一般に、操作キューで操作を常に使用している場合、それらを同時に実行する理由はありません。

次に、で非同期パターンを使用することに本当に興味がありNSOperationます。Dave Dribin並行操作)による優れたチュートリアルを見つけました。私は彼のポストの全体的な意味を理解しました。

デリゲートを呼び出すことができなかったため、非同期パターンを使用することはできません(たとえば、非同期NSURLConnection要求を使用する)。終了するmainと、操作は削除されます。解決策は、メソッドをオーバーライドしstartて操作のライフサイクルを制御することです...そして実行ループの処理は面倒な場合があります。

今、彼の投稿を理解しようとすると、私の疑問はstart、メインスレッドでメソッドを実行する必要があることです。

- (void)start
{
    if (![NSThread isMainThread])
    {
        [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
        return;
    }

    // other code here...
}

非同期APIを処理する場合、開始時にメインスレッドで非同期呼び出しを開始し、終了するまで操作を実行し続けることができます。

理由を教えていただけますか?

前もって感謝します。

4

2 に答える 2

11

私の意見では、のisConcurrentプロパティNSOperationは紛らわしい名前が付けられています。それは本当に「非同期」を意味します。つまり、それ-startが呼び出されると、操作が完了まで実行されたかどうか(非同期)に関係なく、すぐに戻りますか?または、操作が完了するまで(同期)戻りませんか?

NSOperationQueueAppleのドキュメントに記載されているように、操作がキューに入れられた場合、キューはワーカースレッドで操作を呼び出すため、これはそれほど重要ではありません。同期している場合、そのワーカースレッドは、完了するまでその操作に専念します。非同期の場合は-start、操作が完了する前に戻り、ワーカースレッドは他の作業を続行できます。

-start問題は、非同期メソッドが操作の作業を継続することをどのように確認するかということです。それは仕事をするために別のスレッドを生み出すことを必要とするかもしれません、しかしそれはばかげていますNSOperationQueue糸脱毛を処理させる方が良いです。

多くの場合、外部イベントによって駆動される実行ループソースを使用します。NSURLConnection非同期モードでは、そのようなものです。ただし、その場合は、実行ループソースをスケジュールするスレッドがa)固執し、b)実行ループを実行することを確認する必要があります。のワーカースレッドNSOperationQueueも信頼できません。

繰り返しになります、このような操作ごとに独自のスレッドを作成して、実行ループを実行することもできますが、これは不要であり、操作を同期させてキューに入れるよりも利点はありません。

すでに知っているスレッドの1つは、メインスレッドです。したがって、多くの場合、メインスレッドの実行ループで実行ループソースをスケジュールするのが最適です。注意すべき唯一のことは、実行ループソースのハンドラーをトリガーする外部イベントに応答して、メインスレッドで長時間実行される作業を行わないことです。したがって、たとえば、NSURLConnection受信したデータを使用してデリゲートメソッドを呼び出す場合、そのデータに対して高額な計算を行うことはありません。または、必要に応じて、その高額な計算を別のスレッドに移動します。

もう1つの可能性、中間点は、多くの非同期操作のワーカーとなる独自のスレッドを1つ作成することです。したがって、メインスレッドまたは操作ごとのスレッドを使用するのではなく、実行ループに停車しているだけの仕事をしている単一のスレッドを使用します。すべての非同期操作は、そのスレッドの実行ループで自分自身をスケジュールします。ただし、このアプローチの必要性や利点はそれほど多くありません。

于 2012-06-02T15:54:15.180 に答える
1

デイブは、投稿のメインスレッドにstartメソッドをシャントする動機に取り組んでいると思います。

更新2009-09-13:これは10.6以降は当てはまりません。startメソッドは、10.6以降、常にバックグラウンドスレッドで呼び出されます。メインスレッドのみと実行ループに依存する非同期APIを適切に機能させるには、作業をメインスレッドにシャントする必要があります。これについては、フォローアップの投稿で詳しく説明します。

于 2012-06-02T15:15:16.737 に答える