我是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
}发布于 2014-12-12 18:00:56
您的StackOverflowException可能是由重复按下按钮引起的。这将导致递归调用BeginMonitoringClick()方法,这最终会使堆栈溢出。
如果没有看到其余的代码,就不可能确切地知道。在只使用DoEvents()一次的代码中,到处都使用它是很常见的。您可能在其他地方也会有类似的bug,每个bug都会导致问题。
就我个人而言,我希望微软从未包括过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-12 16:40:53
我建议你使用背景线。
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();https://stackoverflow.com/questions/27447297
复制相似问题