0

我是 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
}
4

2 回答 2

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()稍后在您希望发生这种情况时调用。

于 2014-12-12T18:00:56.433 回答
-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();
于 2014-12-12T16:40:53.577 回答