1

最近、ようやく別スレッドが機能するようになりました。今、私は同期をマスターしようとしています。

私の知る限り、スレッドを一時停止することThreadName.Suspend()はお勧めできません。While最初は、ループを使用してスレッドをブロックしました。後で、これがリソースを消費することに気付いたので、ループを に置き換えようとしていますAutoResetEvent

ここにいくつかのコードがあります(完全なコードかどうか教えてください):

private void combTester(object sender, EventArgs e)//happens in a timer, because it manipulates the GUI
{
    if (!timer2Block)
    {
        //stuff happens
        genBlock = false;//unblocks the thread
        timer2Block = true;//blocks itself
        //debugging stuff happens
    }
    if (done)
        timer2.Enabled = false;
}

private void combGenerator(int currEl, int begVal)
{
    //setting a variable
    for (int c = begVal; c <= currEl + totalCells - maxCells; c++)
    {
        while (genBlock && !abortTime)
        {
            if (abortTime)
                return;
        }
        genBlock = true;//blocks itself
        //some recursive stuff happens,
        //because of which I was forced to use a thread instead of timers
    }
}

Wait()メソッドとメソッドを別の場所に配置しようとしましたSet()が、トレッドとタイマーの両方がブロックされ、プログラムをデバッグする方法がわかりません。

Whileでは、ループをに置き換えるにはどうすればよいAutoResetEventですか?

4

2 に答える 2

1

ワーカースレッドの「一時停止」制御が必要な場合はManualResetEvent、イベントをシグナル状態に保ち、スレッドを一時停止するときにリセットする必要があります。

private void combGenerator(int currEl, int begVal)
{
    for (int c = begVal; c <= currEl + totalCells - maxCells; c++)
    {
        manualResetEvent.WaitOne();
        // do stuff
    }
}

と を実行することで、combGeneratorスレッドを一時停止/一時停止解除できるようになりました。manualResetEvent.Reset()manualResetEvent.Set()

これをさらに拡張して、別のシグナルをスローすることで「中止」シグナルを含めることができますManualResetEvent(これは である可能性もありますがAutoResetEvent、区別が重要ではない場合にのみ何かを実行するため):

    var events = new[] { abortEvent, pauseEvent }; // order MATTERS!
    for (int c = begVal; c <= currEl + totalCells - maxCells; c++)
    {
        var index = WaitHandle.WaitAny(events);
        if (index == 0) {
            // abort!
        }

        // do stuff
    }

ここでの魔法は内部で起こりますWaitAny。このメソッドは、いずれかのイベントがシグナル状態になるのを待機し、複数の場合、シグナル状態になったイベントの中で最小のインデックスを返します。中止すべきかどうかを判断できるようになるため、これは非常に重要です。

通常の動作中abortEventは通知されませんpauseEventので、WaitAnyすぐに戻り1ます。pauseEventがリセットされた場合WaitAny、いずれかのイベントが再度通知されるまでブロックされます。そして、 が通知された場合abortEventは、終了の合図であるWaitAnyを返し0ます。

于 2013-09-28T21:27:35.403 に答える