【问题标题】:Temporarily disable button暂时禁用按钮
【发布时间】:2011-04-07 11:10:45
【问题描述】:

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

表单上只有一个按钮。该按钮调用一个函数,该函数需要 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 函数,我可以确定打印完成的时间,然后才能再次启用按钮。

【问题讨论】:

  • 您是否尝试过 this.AcceptButton=null 并在完成设置后设置 this.AcceptButton=button1 以及切换 Enabled
  • @jfs:在问题中查看我的编辑。

标签: winforms button


【解决方案1】:

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

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

修正提案:

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

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

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

【讨论】:

  • 这正是发生在我身上的事情,DoEvents 确实解决了这个问题。我不擅长 winforms,所以我不明白为什么 Rhapsody 建议的解决方法会起作用,因为问题不在于禁用和启用按钮,而是在启用按钮后立即排队和操作的消息?
  • @Shaikh Owais:实际上,我想说 Application.DoEvents() 是这里的解决方法。查看我的编辑。
【解决方案2】:

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

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

【讨论】:

  • 效果很好,谢谢。我想知道这是否可以在同一个线程中完成。
【解决方案3】:

试试这个代码。

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();
}

希望对你有帮助。

【讨论】:

  • 这行不通。 GUI 仍然停留在 WaitOne() 调用中并且不会处理事件。点击会累积,下次处理时,按钮的 enabled 属性将为 true 并且处理程序将执行
猜你喜欢
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多