5

ManualResetEvent を使用してスレッドを同期するアプリケーションを使用しています。FxCop から、それらのオブジェクトを破棄するように言われました。私は同じことを言った次の議論を見つけました:

EventWaitHandle を Dispose() または Close() する必要がありますか?

しかし、ManualResetEvent のインスタンスを破棄するタイミングがわかりません。

次の簡略化されたコードは、問題を示しています。

private void btn_Click(object sender, EventArgs e)
{
    var mre = new ManualResetEvent(false);
    new Thread(() => this.SetEvent(mre)).Start();
    for (int i = 0; i < 10; ++i)
    {
        new Thread(() => this.WaitFor(mre)).Start();
    }
}

private void SetEvent(ManualResetEvent manualResetEvent)
{
    Thread.Sleep(10000);
    manualResetEvent.Set();
}

private void WaitFor(ManualResetEvent manualResetEvent)
{
    manualResetEvent.WaitOne();
}

問題は、ManualResetEvent の複数のインスタンスが存在し、複数のスレッドが各インスタンスを待機していることです。

リスト内のインスタンスを暗記すると、いつ破棄するかわかりません。WaitOne() 呼び出しの後に破棄すると、複数回破棄され、他のスレッドがまだ待機している間に破棄される可能性があります。

イベントを作成したスレッドには、イベントへの参照がありません。この MRE を待っている他のスレッドがあるため、setter-thread はそれを破棄しないでください。前述のように、待機中の各スレッドはそれを破棄できません。

問題は、この ManualResetEvent をいつ破棄する必要があるかということです。

4

1 に答える 1

5

ManualResetEvent不要になったら破棄する必要があります。あなたの本当の質問は、「それがもう必要ないことをどのように知ることができますか?」ということです。

通常、スレッドが完了すると何かが通知され、スレッドでJoinを呼び出します。または、スレッドが何らかのイベントを設定して、終了したことを示します。複数のスレッドがある場合、それらはすべてCountdownEventを通知できます。スレッド通知を管理するには、他にもいくつかの方法があります。

重要なのは、リソースを割り当てる場合、それらが正しく破棄されていることを確認するのはあなた次第です。上記のコードでは、どのスレッドが実行されているか、またはどのスレッドがどの に関連付けられているかを追跡する方法がありませんManualResetEvent。MRE が適切に破棄されていることを確認したい場合は、MRE を追跡するだけでなく、どのスレッドがそれを使用しているか、どのスレッドが作業を完了したかを追跡する必要があります。スレッドは、物を処分できるように行われます。

あなたの特定の状況で、本当にこのように MRE を使用する必要がある場合は、スレッドと MRE への参照を含むデータ構造と、CountdownEventスレッドが完了したときにスレッドが通知するデータ構造を作成するでしょう。何かのようなもの:

class WorkUnit
{
    public List<Thread> Threads;
    public ManualResetEvent MRE;
    public CountdownEvent CE;
}

スレッドが終了すると、次のようになります。

workUnit.CE.Signal();

プログラムの他の部分 (おそらくメイン スレッド) は、ワーク ユニットのリストを定期的にチェックします。そのリストの各項目に対して、次のことを行います。

if (workUnit.CE.WaitOne(0))
{
    foreach (Thread t in workUnit.Threads)
    {
        t.Join();
    }
    // dispose the MRE and the CE
    // and remove the work unit from the list
}

はい、大変な作業です。この種のことを行う必要がないようにプログラムを構成できる場合は、おそらく最善です。

于 2013-08-29T15:53:57.443 に答える