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

时间:2011-03-10 13:18:57

标签: c# .net

当我使用System.Windows.Forms.Timer类并完成使用它时,我无法禁用它..即使我将其属性Enabled设置为false,它也会打勾。代码有什么问题?这是一个例子:

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

6 个答案:

答案 0 :(得分: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"); 
}

这种问题也是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;
    }
}

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

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

答案 1 :(得分:2)

这是因为MessageBox.Show阻止,直到用户按下OK 在按下10个OK按钮之后,MessageBox下面的代码才会执行 但即使执行被阻止,计时器也会继续启动。

试试此代码

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

(刚刚移动了MessageBox)

答案 2 :(得分:1)

timer1.Stop()怎么样?我对这门课不太熟悉,但很快就查了一下:Timer Class

答案 3 :(得分:1)

它也适合我。我将计时器放在表单中,单击按钮,我正在调用timer1.start(),并将以下代码放入tick事件及其工作中。

int i = 0;
private void timer1_Tick(object sender, EventArgs e)
{
    i++;
    this.Text = i.ToString();
    if (i == 10)
    {
        timer1.Enabled = false;
    }
}

您需要致电Stop。

int i = 0;
private void timer1_Tick(object sender, EventArgs e)
{
    i++;
    if (i == 10)
    {
        timer1.Stop();
    }
}

答案 4 :(得分:1)

试试这个:

int counter = 0;
private void timer1_Tick(object sender, EventArgs e) { 
    MessageBox.Show("Hello"); 
    counter++; 
    if (counter == 10){
       timer1.Stop();
       timer1.Dispose();
       timer1 = null;
    }
}

答案 5 :(得分:1)

我很确定MessageBox是罪魁祸首。也许如果你对计时器处理程序使用一个较短的执行间隔,那么如果执行重叠,这可能会导致你的代码不正常地运行。

在这种情况下,问题是处理程序执行并显示MessageBox,这会暂停当前作用域的执行,直到用户确认提示,同时处理程序再次启动,显示另一个提示,另一个,等等。此时,我们有多个MessageBox等待输入,但counter甚至没有增加一次。当我们在提示上单击“确定”时,counter会根据需要递增,但此时的值为1,而不是表示显示的提示数量的值。这意味着如果时间过长,将显示另一个提示,直到用户至少在10提示上单击“确定”。

如果流程已在进行中,您可以尝试禁止执行,以防止并发运行:

private readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();

int counter = 0;
private void timer1_Tick(object sender, EventArgs e) 
{
    if (Locker.TryEnterWriteLock(0))
    {
        try
        {
            MessageBox.Show("Hello");
            Counter++;
            if (Counter == 10)
            {
                Timer.Enabled = false;
            }
        }
        catch { }
        finally
        {
            Locker.ExitWriteLock();
        }
    }
}