2016-07-23 4 views
6

アップルのNSOperationによると、並行操作ではmain、同時操作ではstartメソッドをオーバーライドする必要があります。しかし、なぜ?NSOperation、開始対メイン

答えて

0

私は、コンカレント対ノンコンカレントは単なるフラグではなく、非常に大きな違いだと思います。 2つの異なるメソッドを持つことによって、非並行のものを使用する必要がある場合に並行操作を使用しないこと、またはその逆を行うことを絶対に確実にします。

あなたが間違っている場合、あなたのコードはこの設計のために絶対に動作しません。それはあなたがすぐにそれを修正するので、あなたが望むものです。メソッドが1つしかなかった場合は、非並行ではなく並行を使用すると、非常に微妙なエラーが発生する可能性があります。また、同時実行ではなく非同時実行では、パフォーマンス上の問題が発生する可能性があります。

+0

メインフィニッシュ後に「isFinished」がtrueに設定されていると思います。それは理由の1つかもしれません。 – Anshu

+0

この回答は、「同時」とは「バックグラウンドで実行される」という意味です。これはNSOperationでの「同時」の意味ではありません。並行操作と非並行操作の両方をバックグラウンドで実行できます(マルチスレッド違反のため「微妙なエラー」があります)。キューなしで実行すると、どちらかが完全に同期する可能性があります。キューを使用して実行した場合(10.6以降)、両方ともバックグラウンドスレッドで実行されます。デフォルトの 'start'は' main'を呼び出します。並行操作は 'start'をオーバーライドする必要があります(デフォルトでは非並行動作となります)。それが違いの源です。 –

8

まず、「同時」および「非同時」は、人々を混乱させる傾向があり(「非同期/同期」と同義語として使用される)、幾分特殊な意味を持つことに注意してください。 「並行」とは、「オペレーションがそれ自身の並行性と状態を管理する」ことを意味します。 「非並行」とは、「操作は並行性を管理するために他のもの(通常はキュー)を必要とし、デフォルトの状態処理が必要です」という意味です。

startはすべてデフォルトの状態処理を行います。その部分はisExecutingに設定し、次にmainを呼び出し、mainが返ってくるとisExecutingをクリアし、isFinishedに設定します。自分の状態を処理しているので、あなたはそれを望んでいません(mainを終了して操作を終了したくない場合)。したがって、startを実装し、superを呼び出さないといけません。必要ならばmainメソッドを使用できますが、すでにstartをオーバーライドしています(それはmainというものです)。ほとんどの人はすべてのコードをstartに入れています。

一般的に、並行操作は使用しないでください。彼らはあなたが意味することはめったにありません。彼らはは間違いなくは「バックグラウンドで動くもの」を意味するものではありません。どちらの種類の操作もバックグラウンドで実行できます(また、にはがバックグラウンドで実行されません)。問題は、デフォルトのシステム動作(非並行)か、すべてを自分で処理する(同時)かどうかです。

それを自分で処理するという考え方が「NSThreadをスピンアップする」なら、あなたはそれを必要とするC/C++ライブラリとインターフェースするためにこれをやっていない限り、間違いを犯していると思います。それはキューを作成している場合は、おそらくそれを間違っている(NSOperationはこれを避けるためのすべての種類の機能があります)。 「バックグラウンドで手動で処理する」のようなものなら、おそらく間違っているでしょう。デフォルトの(並行していない)動作は、あなたがやろうとしている動作よりもほぼ確実に優れています。

並列処理が役立つのは、使用しているAPIがすでに並列処理を処理している場合です。 mainが返されると、非並行操作が終了します。だから、もしあなたの操作がNSURLConnectionのような非同期のものを包むならば?これを処理する1つの方法は、ディスパッチグループを使用し、mainの最後にdispatch_waitを呼び出して、すべてが完了するまで返さないようにすることです。それで大丈夫です。私はいつもそれをする。しかし、ブロックされていないスレッドはブロックされてしまい、リソースが浪費され、複雑なコーナーケースでデッドロックが発生する可能性があります(実際にはです)。Appleは可能だと言っていますが、それを目的にさえも起こすことができる)。

これを実行する別の方法は、自分自身を同時操作として定義し、NSURLConnection代理人メソッドで手作業でisFinishedを設定することです。 Dispatch I/Oのような他の非同期インターフェイスをラッピングしている場合、同様の状況が発生し、並行処理がより効率的になる可能性があります。

(理論的には、並行操作は、キューを使用せずに操作を実行する場合にも役立ちます。これは意味があるところで非常に畳み込まれたケースを想像することはできますが、そのボートでは、あなたが何をやっているのか分かっていると思います)。

しかし、何か質問がある場合は、デフォルトの非並行動作を使用してください。ほとんどの場合、(特にディスパッチグループを使用する場合は)ほとんど手間をかけずにそのような振る舞いを得ることができます。次に、ドキュメント内の「並行」というやや混乱した説明の周りに頭を抱く必要はありません。

関連する問題