这个阻塞线程如何调用“释放”自身?

时间:2015-12-11 09:23:29

标签: c# multithreading winforms timer

我正在运行一个基本的单线程应用程序。

通常,在调用System.Windows.Forms.MessageBox.Show()时,可以预期此调用会有效阻止进一步执行,直到此方法返回。

然而,当使用System.Windows.Forms.Timer时,* 相同的 *主题似乎以某种方式释放自身并且Timer的{​​{1}}事件正在触发同样的话题。

到底是怎么回事?我觉得这可能与穿线公寓有关,但我想澄清一下。

作为控制台应用程序以其最简单的形式重新创建,如下所示:

Tick

输出:

  

线程10已进入
  线程10已进入
  线程10已进入
  线程10已进入
  线程10已进入

1 个答案:

答案 0 :(得分:6)

当显示模式窗口(如消息框)时,Windows消息泵将继续运行。

如果没有,当你在它前面移动模态窗口时,模态窗口后面的窗口显示将不会被更新。

由于Windows消息仍在被抽取,因此" WM_TIMER"消息仍然会被发送到非前景窗口,因此您将看到您注意到的行为。

需要注意的关键是Windows计时器会导致Windows发布" WM_TIMER"消息进入窗口的事件队列,只要窗口的消息泵正在运行,定时器事件将继续处理。

避免这种重新进入问题的一种常见方法是在处理勾选时禁用计时器。

例如,将您的tick处理代码放入名为handleTimer()的方法中,然后像这样处理tick:

private void timer_Tick(object sender, EventArgs e)
{
    timer.Enabled = false;

    try
    {
        handleTimer();
    }

    finally 
    {
        timer.Enabled = true;
    }
}

(如果发生异常,您可能不希望重新启用计时器,在这种情况下,您不需要上面的try/finally逻辑。)