2011-04-07 129 views
3

应该是简单的,但... :)暂时禁用按钮

我在表格上只有一个按钮。按钮调用一个函数,这需要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函数,我可以确定打印何时完成,只有这样才能再次启用按钮。

+0

你试过了** this.AcceptButton = null **,并且在完成设置后** this.AcceptButton = button1 **除了切换**启用** – V4Vendetta 2011-04-07 11:20:48

+0

函数做了什么? – jfs 2011-04-07 11:27:12

+0

@ V4Vendetta - 没有区别。 – sventevit 2011-04-07 11:27:24

回答

1

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

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

+0

很好,谢谢。我想知道这是否可以在同一个线程中完成。 – sventevit 2011-04-07 11:37:09

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

希望它有帮助。

+1

这不起作用。GUI仍然停留在WaitOne()调用中,不会处理事件。点击次数会累积,下一次处理它们时,按钮的启用属性将为true,处理程序将执行 – 2013-12-19 15:20:20

3

最近我有同样的问题,我决定后我的解释:

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

修复建议:

您可以插入行 “Application.DoEvents()” 只是前行 “button1.Enabled = TRUE;”这样排队的消息将在它仍然被禁用时到达按钮,并且按钮现在将丢弃它们。

声明:似乎使用Application.DoEvents()并不被认为是一种好的做法。但是,它很好地显示了在这种特殊情况下会发生什么。

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

+0

这正是我发生的情况,DoEvents确实解决了这个问题。我对winforms不太好,所以我不明白为什么Rhapsody提出的解决方法能够工作,因为问题并不在于禁用和启用按钮,而是在按钮启用后排队并执行了操作的消息? – 2014-06-12 23:55:19

+0

@Shaikh Owais:实际上,我会说Application.DoEvents()是解决方法。看我的编辑。 – 2014-06-13 09:45:29