0

detachNewThreadSelector reftoTargetselfを使用して新しいスレッドを作成しています。

スレッドの目的は、動きをポーリングし、必要に応じて画像をロードすることです。オブジェクトに設定されているメインスレッドでアトミックブール値がtrueに設定されている場合にのみ、ループして終了しますdealloc

この問題は、(detachNewThreadSelectorリファレンスから)これが原因で発生します。

オブジェクトaTargetとanArgumentは、デタッチされたスレッドの実行中に保持され、その後解放されます

つまり、スレッドは継続的にポーリングするため、オブジェクトの保持カウントは常に(最小)1になります。deallocしたがって、呼び出されることはありません。

だから私の質問は:ポーリングスレッドの存在を考慮に入れてオブジェクトの割り当てを解除するにはどうすればよいですか?

私が今持っている唯一のアイデアは、オブジェクトのdestroyThread関数を作成することです。これは、オブジェクトが破棄されると予想されるすべての場所から呼び出されるエンドスレッドブール値を設定します。これはエラーが発生しやすいようですが、より良い解決策はありますか?

前もって感謝します。

アップデート

私は別の解決策を考えました-保持カウントが1であるかどうかを検出するスレッドで-それが1である場合、スレッドがオブジェクトを存続させていることがわかっているので、ループを中断してdeallocが呼び出されます。これは堅牢なソリューションですか?

4

1 に答える 1

2

まず、避けてくださいdetachNewThreadSelector:。あなたがそれでやろうと思っていることは、ほぼ確実にディスパッチキューまたはでうまくやっていますNSOperationQueue。手動でスレッドを作成する必要がある場合でも(最近のObjCでは非常にまれです)、直接対話できないスレッドを作成するスレッドをNSThread使用するよりも、明示的なオブジェクトを作成して保持する方が適切です。detachNewThreadSelector:

特定の質問に対して、独自のスレッドを作成する場合は、そのブール値を。以外の場所に設定する必要がありますdealloc。これは、プログラムの他の部分がシャットダウンするように指示する必要があることを意味します。この方法で手動スレッドを使用して、解放して自動的にクリーンアップすることはできません。


編集:決して、決して呼び出さないでくださいretainCount。関係retainCountする解決策は良い解決策ではありません。より一般的なケースでの使用に関するさまざまな実際的な問題はさておき、retainCountこの場合、手動の参照カウントに結びつきます。できるだけ早くARCに切り替える必要retainCountがあり、ARCでは違法です(ARCの前は違法であったはずですが、最終的には問題を強制するための非常に良い言い訳ができました)。ARCでソリューションを実装できない場合、それは良いソリューションではない可能性があります。

繰り返しになりますが、最善の解決策は、GCDディスパッチキュー(または一般にディスパッチキューで実装される操作)を使用することです。手動のスレッド管理よりも、ほとんどすべての問題に対して非常に効率的で効果的です。

レガシーコードに手動スレッドを使用する必要があり、この種の自動破棄を維持する必要がある場合、解決策はスレッドを所有するヘルパーオブジェクトです。オブジェクトは、スレッドとの保持ループを持つヘルパーオブジェクトを所有しています。オブジェクトの割り当てが解除されると、スレッドにシャットダウンするように指示します。これにより、保持ループが中断され、ヘルパーオブジェクトが削除されます。これは、保持ループを管理するための標準的な方法です。

詳細については、Appleの「スレッドからの移行」を参照してください。

于 2012-07-19T19:12:29.480 に答える