禁用定时器..为什么我不能?

1 .net c#

当我使用System.Windows.Forms.Timer类和使用它,然后完成我不能禁用它..它蜱即使我的属性设置Enabledfalse.代码有什么问题?这是一个例子:

int counter = 0;
private void timer1_Tick(object sender, EventArgs e) { 
    MessageBox.Show("Hello"); 
    counter++; 
    if (counter == 10){
       timer1.Enabled = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 7

这是一个由MessageBox.Show()调用引起的细微错误.MessageBox抽取消息循环以保持UI活跃.这允许Tick事件处理程序再次运行,即使它已从上一个tick打开.在单击"确定"按钮之前,计数器变量不会增加.因此,屏幕会填充消息框,并且在您单击"确定"按钮十次之前不会停止.

您需要显示消息框之前递增计数器.固定:

int counter = 0;
private void timer1_Tick(object sender, EventArgs e) { 
    counter++; 
    if (counter > 10) timer1.Enabled = false;
    else MessageBox.Show("Hello"); 
}
Run Code Online (Sandbox Code Playgroud)

这种问题也是DoEvents()获得如此糟糕声誉的原因.编写能够正确处理消息循环引起的重入的代码非常困难.您需要保留布尔标志,表明代码已经处于活动状态.这是解决问题的另一种方法:

int counter = 0;
bool showingBox = false;

private void timer1_Tick(object sender, EventArgs e) { 
    if (showingBox) return;
    showingBox = true;
    try {
        MessageBox.Show("Hello"); 
        counter++;
        if (counter == 10) timer1.Enabled = false;
    }
    finally {
        showingBox = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

您现在一次只能获得一个消息框,可能就是您真正想要的内容.

我应该提一下,这种重新入侵的问题对计时器非常具体.对话框采取对策以避免重新入侵问题,它会禁用应用程序中的所有窗口.这可确保用户无法执行关闭主窗口或单击再次显示对话框的按钮等操作.两者都是灾难性的灾难.这会处理大多数"意外"Windows通知,基本上是用户生成的任何消息.边缘情况是一个计时器(WM_TIMER未被禁用),其事件处理程序具有UI效果.