我的System.Threading.Timer(有一个回调)永远不会可靠地触发。这是我的编程任务的一部分,我输入计时器应该从文本框运行的时间。
计时器声明如下:
System.Threading.Timer timer = new System.Threading.Timer(WorkerObject.callback, null, delay, Timeout.Infinite);
延迟只是一个int
,描述了第一次触发回调的延迟(它只能触发一次)。
回调方法如下:
public static void callback(Object stateinfo)
{
stop = true;
}
所有这一切都设置了一个标志为true,它停止一个循环(由ThreadPool上的一个线程运行,实际上是停止线程)。
循环如下:
while (!stop)
{
currentTextbox.Invoke(new Action(delegate()
{
currentTextbox.AppendText((counter++) + Environment.NewLine);
currentTextbox.Update();
}));
}
我的问题是,对于超过5000毫秒的任何延迟,stop
变量始终为false。有没有办法“强迫”回调始终开火?
答案 0 :(得分:10)
您需要保持对计时器的引用。
很可能是定时器对象被垃圾收集,它将运行其终结器,停止计时器。
所以只要你需要让计时器存活,就要坚持参考。
答案 1 :(得分:4)
我建议使用CancellationTokenSource
:
static CancellationTokenSource Cancel = new CancellationTokenSource();
public static void Callback(object state)
{
Cancel.Cancel();
}
和你的循环:
while (!Cancel.IsCancellationRequested)
{
...
}
这比使用volatile
更清晰,并且在将简单的概念证明移动到单独的类时更容易移植。有关详细信息,请参阅我的博客Polling for Cancellation。
答案 2 :(得分:1)
运行时抖动可能会将while(!stop)
条件优化为while(true)
。
将stop
变量标记为volatile。
private volatile bool stop = false;