当前位置:   WINDOWS > 正文

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

c#,multithreading,timer,winforms,windows,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具,前端开发工具,开发人员工具,站长工具

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

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

但是,在使用的时候System.Windows.Forms.Timer,似乎**线程以某种方式释放本身和TimerTick事件被烧成这个相同的线程.

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

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

class Program
{
    static void Main(string[] args)
    {
        new Program();
        while (true)
        {
            System.Windows.Forms.Application.DoEvents();
        }
    }

    private System.Windows.Forms.Timer timer;

    public Program()
    {
        timer = new System.Windows.Forms.Timer() { Interval = 2000 };
        timer.Tick += timer_Tick;
        timer.Start();
    }

   private void timer_Tick(object sender, EventArgs e)
    {
        Console.WriteLine(string.Format("Thread {0} has entered", Thread.CurrentThread.ManagedThreadId)); 
        var result = MessageBox.Show("Test");
        Console.WriteLine(string.Format("Thread {0} has left", Thread.CurrentThread.ManagedThreadId)); 
    }
}

输出:

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

Matthew Wats.. 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上面的逻辑.)



1> Matthew Wats..:

当显示模式窗口(如消息框)时,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上面的逻辑.)

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号