用AutoResetEvent替换While循环以阻止线程

时间:2013-09-28 21:13:22

标签: c# multithreading

最近,我终于能够创建一个单独的线程了。现在我正在尝试掌握同步。

据我所知,暂停一个帖子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

2 个答案:

答案 0 :(得分:1)

如果您想要对工作线程进行“暂停”控制,那么您应该使用ManualResetEvent:保持事件发出信号,并在您希望线程暂停时重置它:

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

现在,您可以相应地执行combGeneratormanualResetEvent.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,这是退出的提示。

答案 1 :(得分:0)

你可以使用另一个标志来检查它是否是递归调用,根据你可以决定继续或等待。

示例:

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