2009-05-07 19 views
2

私は抽象クラスを持っていて、そのコンストラクタ内に無限ループスレッドを生成しています。クラスの使用が終了したときにこのスレッドが中止されるようにするにはどうすればよいでしょうか?C#:スレッドを正しく解放する

IDisposableを実装する必要がありますか?単にこれを使用しますか?

public void Dispose() 
{ 
    this.myThread.Abort(); 
} 

私はAbort()が悪であることを読みました。 Dispose()はスレッドがtrueをチェックしてループを終了するためのプライベートブールフラグを設定する必要がありますか?スレッドのループで

public void Dispose() 
{ 
    this.abort = true; 
} 

// ...

if (this.abort) 
{ 
    break; 
} 

は、代わりにBackgroundWorkerのクラスを使用しますか?

答えて

3

無限ループを使用する代わりに、メインクラスによってループ条件として設定できるブール値フラグを使用します。終了したら、ループを正常に終了できるようにフラグを設定します。 IDisposableを実装する場合は、フラグを設定し、スレッドが終了するのを待ってから戻ってください。

キャンセル可能なBackgroundWorkerクラスを実装することはできますが、基本的には同じことが達成されます。

本当に欲しいのなら、信号を送信した後に自分自身で終了する時間を与えることができます。終了しない場合、シャットダウン時にWindowsが実行するようにスレッドを中断できます。

私がThread.Abortが「邪悪」と考えられる理由は、物事が未定義の状態になるということです。ただし、プロセス全体を強制終了するのとは異なり、残りのスレッドは引き続き実行され、問題に陥る可能性があります。

+0

C#はこのようなフラグのためのメモリバリアを必要としませんか? – bdonlan

+1

です。あなたは "揮発性"キーワードを使用する必要があります。下の私のポストを参照してください。 –

+1

実際には、フラグ値は最終的には揮発性なしでも(少なくともx86とx64では)表示されます。時間がかかることがありますが(数ミリ秒)、表示されます。理論的には、スコットはそうです、実際にはここでは揮発性が使われるべきです。 –

0

私はBackgroundWorkerメソッドを提案します。実装が比較的簡単で、うまくクリーンアップできます。

4

"lc"(それ以外の点では素晴らしい)の答えをさらに広げたいと思います。

彼のアプローチを使用するには、論理フラグを "volatile"とマークする必要があります。これは "メモリバリア"を導入し、バックグラウンドスレッドが(レジスタとは対照的に)メモリからそれを取得する変数を読み取るたびに、変数が書き込まれるとCPUキャッシュ間でデータが転送されることを保証します。

+0

+1非常に良い点。 –

関連する問題