スレッドが何をしているかによって異なります。スレッドが無期限に実行される可能性のある長時間実行されるタスクを実行している場合、そのスレッドをリソース (ガベージ コレクションされない) と見なします。たとえば、スレッドが特定の状態を無期限にポーリングするように設計されているか、キューからアイテムを消費するように設計されているか (スレッドプール スレッドがタスクを消費したり、TCP サーバーが新しい接続を消費したりするように) などを考えてみてください。クラスを破棄すると、このスレッド リソースが解放されます。この場合、null に設定してもあまり役に立ちません。それよりもDispose
おそらく、同期イベント (またはおそらく CancellationToken) にフラグを立てて、無限タスクを終了する必要があることをスレッドに通知する必要があります。その後、スレッドを破棄するスレッドは、スレッドが終了 (結合) するまでしばらく待機する必要があります。結合の場合と同様に、デッドロック シナリオに注意し、スレッドが終了を拒否した場合は代替アクションを検討してください。明らかな理由から、ファイナライザーでこの結合を行いません。
class A
私が言っていることの例として、あなたが実際class MyTcpListener
に、特定のポートで新しい TCP 接続をリッスンして無期限に待機するように設計されているシナリオを考えてみましょう。次に、次の (あまりありそうにない) コードで何を期待するかを考えてみましょう。
using (MyTcpListener listener = new MyTcpListener(port:1234))
{
// Do something here
}
// Create another one. This would fail if the previous Dispose
// did not unbind from the port.
using (MyTcpListener listener = new MyTcpListener(port:1234))
{
// Do something else here
}
MyTcpListener
のコンストラクターがリスナースレッドを作成することを知っていると仮定すると、Dispose
呼び出しが返された後MyTcpListener
、TCPポートにバインドされなくなる、つまりTCPリスナースレッドが完全に終了することが予想されます。言うまでもなく、リスナーを停止するメカニズムを提供しなければ、リソース リークが発生します。停止メカニズムは「Stop」メソッドの呼び出しである可能性がありますが、個人的には、「Dispose」パターンがこのシナリオにより適していると思います。何かを停止するのを忘れても、通常はリソース リークを意味するわけではないからです。
あなたのコードは異なる仮定を必要とするかもしれないので、シナリオで判断することをお勧めします。スレッドが短時間しか実行されない場合、たとえば、完了すべき既知の有限タスクがあり、その後自然に終了する場合、破棄はそれほど重要ではないか、おそらく役に立たないと言えます。