当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《这个阻塞线程如何调用"释放"自身?》经验,为你挑选了1个好方法。

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

通常,在调用时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上面的逻辑.)

推荐阅读
农大军乐团_697
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有