暂时禁用按钮

时间:2011-04-07 11:10:45

标签: winforms button

应该很简单,但......:)

表单上只有一个按钮。该按钮调用一个函数,该函数需要10秒才能执行(例如)。我希望在此期间暂时禁用该按钮,这样如果用户在执行该功能时按下Enter键,则不会发生任何事情。

但现在它以这种方式工作:用户按Enter键,按钮变为禁用状态。在这10秒钟内,用户再次按下Enter键,当第一个功能完成时,再次调用它。我想阻止这一点,所以只有当按钮再次启用时,Enter键才会起作用。一切都在同一个线程中。

我的代码:

private void button1_Click(object sender, EventArgs e)
{
    Debug.WriteLine("Click");
    button1.Enabled = false;
    Thread.Sleep(3000); // simulate something...
    button1.Enabled = true;
    button1.Focus();
}

编辑:该功能在打印机上打印一些东西。通过打印机的API功能,我可以确定打印完成的时间,然后才能再次启用该按钮。

3 个答案:

答案 0 :(得分:4)

我最近遇到了同样的问题,我决定发布我的解释:

当执行冗长的任务时,用户会在按钮上多次单击。 Windows将这些消息发送到应用程序,但是应用程序无法立即处理它们,因为此时它正忙。因此消息在队列中等待应用程序变为可用。当应用程序完成任务时,按钮的Enabled属性立即设置为True,接下来发生的事情是,它接收排队的消息。此时按钮已启用,因此应用程序会处理新的点击,就像按钮从未被禁用一样。

修正提案:

您可以在“button1.Enabled = true;”行之前插入“Application.DoEvents()”行这样排队的消息将在按钮仍处于禁用状态时到达按钮,按钮现在将丢弃它们。

免责声明:似乎使用Application.DoEvents()并不是一种好习惯。然而,它很好地展示了在这种特殊情况下会发生什么。

我认为Rhapsody建议的解决方案比使用Application.DoEvents()更好。使用BackgroundWorker,我们正在创建第二个线程,因此我们不会阻止GUI线程。由于GUI保持响应,因此禁用该按钮将按预期工作。

答案 1 :(得分:1)

如果您知道要执行的操作需要更长的时间(例如> 5秒),那么异步执行该操作可能会更好。

因此,在这种情况下,请BackgroundWorker。您可以在启动BackgroundWorker之前轻松禁用该按钮,并在其已完成事件中再次启用它。

答案 2 :(得分:0)

试试这段代码。

AutoResetEvent _autoResetEvent = new AutoResetEvent(false);

private button1_click(object o, EventArgs e)
{
    button1.Enabled = false;
    DoPrinterJob();
    button1.Enabled = _autoResetEvent.WaitOne();
}

private void DoPrinterJob()
{
    //Do something.
    _autoResetEvent.Set();
}

希望它有所帮助。