繁体   English   中英

从后台线程调用计时器

[英]Invoke timer from background thread

我想做的事。 我想SomeMethod将被定期调用。 因此,我希望计时器在背景线程方法传递后从背景线程启动。 _timer.Start()被调用,但是TickHandler没有被调用;

码:

using Timer = System.Windows.Forms.Timer;

class TestTimer
    {
        private Timer _timer;
        private Thread _thread;

        public TestTimer()
        {
            // create and initializing timer. but not started!
            _timer = new Timer();
            _timer.Tick += TickHandler;
            _timer.Interval = 60000; // 1 minute

            // create and start new thread
            _thread = new Thread(SomeMethod);
            _thread.Start();
        }

        private void TickHandler(object sender, EventArgs e)
        {
            // stop timer
            _timer.stop();

            //some handling

            // run background thread again
            _thread = new Thread(SomeMethod);
            _thread.Start();
        }   

        private void SomeMethod()
        {
            // some operations

            // start timer!
            TimerStart();
        }

        private void TimerStart()
        {
            _timer.Start();
        } 
    }

通过猴子方法,我发现是否添加这样的代表

internal delegate void TimerDelegate();

并替换字符串

TimerStart(); 

Application.Current.Dispatcher.Invoke(new TimerDelegate(TimerStart), null);

一切正常。 有人可以解释给我什么把戏吗?

您有些混乱了。

如果您想要一个在后台线程触发的计时器,则无需创建一个线程来启动它(哪个线程调用Start方法都没有关系)。 只需使用System.Timers.Timer ,每个Elapsed事件将在线程池线程上发生。

如果您希望在UI线程触发一个计时器,因为看起来您正在使用WPF,则应使用System.Windows.Threading.DispatcherTimer ,而不要使用您一直在使用的Windows Forms计时器。 您应该在特定的UI线程上创建计时器(即,调用new ),并且每个Tick事件都会在该线程上发生。 同样,从哪个线程调用Start都没有关系。

这是对代码中发生的情况的解释:您正在非UI线程上启动Windows Forms计时器。 这种计时器要求消息泵在该线程上运行,以便它可以接收消息。 因为它是非UI线程,所以没有消息泵。 使用Dispatcher.Invoke方法时,将计时器的创建编组回应用程序的主UI线程,这使它可以工作。 但这一切都是多余的。 如果您希望将代码保持原样,只需用DispatcherTimer替换计时器,然后就可以删除Invoke调用。

另外,如果您使用的是.NET 4.5,则可以使用await / async来SomeMethod所有操作(请确保从UI线程调用SomeMethod ):

async Task SomeMethod(CancellationToken ct)
{
    while (!ct.IsCancellationRequested)
    {
        await Task.Run(() => DoAsyncStuff(), ct);

        DoUIStuff();

        await Task.Delay(TimeSpan.FromMinutes(1), ct);
    }
}

MSDN可以为您解释:

注意:Windows Forms Timer组件是单线程的,并且精度限制为55毫秒。 如果需要更高精度的多线程计时器,请使用System.Timers命名空间中的Timer类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM