计时器 - DoEvents的替代实现

时间:2014-12-12 15:53:59

标签: c# timer stack-overflow doevents

我是C#的新手,我需要为我用来监控硬件的小应用程序使用计时器。我找到了一些计时器的参考代码,但它使用了DoEvents()。因为,我运行计时器很长一段时间,有时几天和几个小时,我开始得到堆栈溢出。我现在明白DoEvents()正在引起这种情况,这是大多数人推荐使用的东西。您建议我使用什么功能代替DoEvents来设置我的计时器?

我的代码:

private void BeginMonitoringClick()  { 
{
    myTimer.Tick += new EventHandler(TimerEventProcessor); // myTimer declared elsewhere
    myTimer.Interval = 2000;
    myTimer.Start();

    while(!exitFlag)
    { 
        Application.DoEvents(); 
    }
}

private void TimerEventProcessor(Object myObject, EventArgs myEventArgs){
    // Talk to hardware, see if it is doing OK
}

2 个答案:

答案 0 :(得分:0)

重复按下按钮会导致StackOverflowException 可能。这将导致BeginMonitoringClick()方法被递归调用,最终会溢出堆栈。

如果没有看到剩下的代码,就无法确定。在使用DoEvents()一次的代码中,看到它在整个地方使用的情况并不少见。您可能在其他地方遇到类似的错误,每个错误都会导致问题。

就个人而言,我希望Microsoft从未包含DoEvents()方法,也不包括其兄弟Control.Refresh()Control.Update()。它们的使用可能导致这种基于重入的错误,并且我从未见过实际需要使用它们的情况。总是有一个更合适的解决方案。

正如其他人所说,要修复此代码中的特定错误,您应该只需通过删除循环来更改代码:

private void BeginMonitoringClick()  { 
{
    myTimer.Tick += TimerEventProcessor; // myTimer declared elsewhere
    myTimer.Interval = 2000;
    myTimer.Start();
}

private void TimerEventProcessor(object myObject, EventArgs e) {
    // Talk to hardware, see if it is doing OK
}

您的代码示例中不清楚exitFlag变量的用途,因此我无法解释替代方案。但是,如果它旨在用于暂停/终止对硬件的监控,那么您实际需要做的就是稍后在需要时调用myTimer.Stop()

答案 1 :(得分:-1)

我建议你使用后台线程。

   var tokenSource = new CancellationTokenSource();
        var token = tokenSource.Token;

        var backgroundTask = Task.Factory.StartNew( () => {

            while(!token.IsCancellationRequested)
            {
                Thread.Sleep(2000);
                // do work here
            }

        } , token );


        // save your tokenSource somewhere then you can cancel the thread whenever you are done with it.
        tokenSource.Cancel();