我在 CF 项目 (Windows Embedded CE 6.0)、VS2005 C#、.NET 2.0 中使用 System.Threading.Timer。 这个计时器是需要的,因为像这样使用时不可能重入:
private System.Threading.Timer mainTimer;
private void MainForm_Load(object sender, EventArgs e)
{
// other initializations
mainTimer = new System.Threading.Timer(new TimerCallback(timerMain_Tick),
null, 100, Timeout.Infinite);
}
也就是说,使用了 dueTime 参数,但没有使用 period 参数。只要 period 为 Timeout.Infinite,计时器就会只触发一次。通过检查表单的 InvokeRequired 属性,使计时器成为线程安全的。请注意检查是否为空。这与我的问题有关,我很快就会回答这个问题。
private void timerMain_Tick(object stateInfo)
{
if (mainTimer != null)
{
if (this.InvokeRequired)
{
this.Invoke((ThreadStart)delegate
{
TimerProcess();
});
}
else
{
TimerProcess();
}
}
}
计时器在退出之前必须自行重新启动。
private void TimerProcess()
{
try
{
// do work here
}
finally
{
// retrigger
mainTimer.Change(mainTimerInterval, Timeout.Infinite);
}
}
我遇到的问题是优雅地停止这该死的事情。
private void MainForm_Closing(object sender, CancelEventArgs e)
{
// shut down timer
mainTimer.Change(Timeout.Infinite, Timeout.Infinite);
mainTimer.Dispose();
mainTimer = null;
}
大约 10 次中有 3 次,计时器无论如何都会触发,并且我收到“对象处置”错误。计时器代码尝试在检查 null 后调用计时器方法。 我怀疑计时器触发了,并且在表单关闭时其线程被挂起。我尝试了状态机枚举:
正常状态运行
Form_Closing 设置停止状态并在 Thread.Sleep() 循环中等待停止状态
计时器看到停止并设置停止状态(而不是重新触发自身)
我遇到的问题是计时器线程不会抢占表单关闭方法,因此陷入无限循环。 如何解决这个问题?请注意,在 CF 中,没有 Dispose(WaitHandle) 方法。
最佳答案
有趣的问题。 Compact Framework 中的 Timer 选项似乎不多。
我不确定您的特定代码是如何工作的,因此添加单个静态 bool 值可能会也可能不会解决您的问题。
以下是我如何更改您的代码以接受 timerOK
值。如果这不能解决您的问题,它可以为您提供解决此问题的想法。
private static bool timerOK;
private static long mainTimerInterval = 200;
private System.Threading.Timer mainTimer;
private void MainForm_Load(object sender, EventArgs e) {
timerOK = true;
mainTimer = new System.Threading.Timer(new TimerCallback(timerMain_Tick), null, 100, Timeout.Infinite);
}
private void MainForm_Closing(object sender, CancelEventArgs e) {
timerOK = false;
mainTimer.Change(Timeout.Infinite, Timeout.Infinite);
mainTimer.Dispose();
mainTimer = null;
}
private void timerMain_Tick(object stateInfo) {
if (timerOK && (mainTimer != null)) {
if (this.InvokeRequired) {
this.Invoke((ThreadStart)delegate {
TimerProcess();
});
} else {
TimerProcess();
}
}
}
private void TimerProcess() {
if (!timerOK) return;
try {
// do work here
} finally {
// retrigger
mainTimer.Change(mainTimerInterval, Timeout.Infinite);
}
}
关于timer - 在 Compact Framework 中使用 System.Threading.Timer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17034568/