2

イベントで複数の Set 呼び出しを行うことができる AutoResetEvent を使用しています (例外処理)。追加の Set が呼び出される場合があるため、コードが WaitOne イベントで 2 番目の呼び出しを行うと、ゲートが既に開かれているため、そのまま通過します。

解決策は、WaitOne の直前に Reset を呼び出すことです。よりクリーンなソリューションはありますか、それともこれが唯一の方法ですか? コード例:

private void DoSomeWork()
{
    Thread thrd = new Thread(new ThreadStart(DoSomeOtherStuff));
    thrd.Start();

    //mEvt.Reset();
    mEvt.WaitOne();

    //continue with other stuff
}

private void DoSomeOtherStuff()
{
    /* lots of stuff */

    mEvt.Set();
}

private void ExceptionTriggerNeedsToBreakOutOfDoSomeWork()
{
   mEvt.Set();
}

例外が処理された後、DoSomeWork を再度呼び出す必要がありますが、Set は複数の例外 (または再スローされた例外) で呼び出された可能性があるため、WaitOne はそのまま流れます。

私の解決策は、常に WaitOne の前に Reset を呼び出すことです。これは適切な解決策ですか、設計が不十分ですか、それともこのシナリオを処理する別の種類のイベントがありますか?

編集:コメント付きのリセット(提案された解決策)をイベントの横に移動しました。

4

2 に答える 2

4

これは実際の問題ではありません。WaitOne() 呼び出しは自動的にイベントをリセットします。結局、ManualResetEvent ではなく、AutoResetEvent を使用しました。ここでのキー フレーズは、オート リセットです。

WaitOne() 呼び出しを介してストリームが流れているのを見るのも、ごく普通のことです。優れたマルチコア CPU があり、Start() を呼び出すとすぐにスレッドが開始され、ジョブを完了するのに数マイクロ秒しかかかりませんでした。ミリ秒でも、まばたきよりも速いです。

おそらくもっと重要なのは、ここにスレッドが必要ないということです。1 つを開始してから、それが終了するのを待つのは無意味です。DoSomeOtherStuff() を直接呼び出すだけです。

于 2010-11-05T20:50:37.440 に答える
2

私の懸念は、WaitOne()の前にReset()を呼び出すと、Set()が呼び出されない場合に問題が発生することです。これは、Set()を呼び出し、その直後にWaitOne()を押す前にReset()を押すと発生する可能性があります。Set()を2回呼び出したとしても、両方の後でReset()を呼び出さないという保証はなく、リリースのメカニズムがないスレッドをブロックします。

理想的には、try..catch..finallyブロックを作成し、finallyブロックでSet()を呼び出し、例外処理をメソッド全体に分散させないようにします。それはあなたのために働きますか?

ハンスは、このシナリオではマルチスレッドは不要であるというのは正しいことです。私の懸念は、WaitOne()の呼び出しで本当にマルチスレッド化している場合にのみ当てはまります。

また、セットを複数回呼び出していることも懸念されます...つまり、最初のセットが呼び出されたときに、リソースは実際にロックされたままである必要がありますか?それでももう一度Set()を押すことができる場合は、共有リソースで機能するコードをまだ実行していると私には言います。この場合、WaitOne()の呼び出しでブロックを解除する必要はありません。

また、MSDNからも注意してください。

Setメソッドを呼び出すたびにスレッドが解放されるという保証はありません。2つの呼び出しが近すぎて、スレッドが解放される前に2番目の呼び出しが発生した場合、1つのスレッドのみが解放されます。2回目の呼び出しが発生しなかったかのようです。

いずれにせよ、コードは例外をスローするか、実行して完了するかのどちらかである必要がありますが、両方ではないようです。IEでは、Set()を2回呼び出すべきではありません。

于 2010-11-05T21:02:11.733 に答える