我想防止按钮单击排队。在测试中,我有一个窗体,一个按钮,在代码隐藏中,我有事件处理程序:
private void button1_Click(object sender, EventArgs e)
{
if (_codeRunning)
return;
_codeRunning = true;
//Application.DoEvents();
//button1.Enabled = false;
_click ++;
Debug.WriteLine("Click Number: " + _click);
Task.Delay(5000).Wait();
//button1.Enabled = true;
_codeRunning = false;
}
当我运行调试并快速单击按钮两次或三或四次时,“调试输出”会在每次单击后大约五秒钟显示每次单击。我想要显示的是单击并放下其余部分,直到第一个事件完成。
我还尝试禁用该按钮,以及从Button_click事件中临时删除该处理程序。都是一样的结果。
最佳答案
像这样挂断UI线程时会遇到各种各样的麻烦。这当然是其中之一,当用户疯狂按下按钮以尝试使事情发生时,没有什么愉快的事情发生。当然,这些点击不会丢失,它们会存储在消息队列中。当事件处理程序停止运行时,再次激活您的Click事件处理程序。
了解如何使用BackgroundWorker或Task类来避免此类麻烦非常重要。只需设置按钮的Enabled属性即可解决此问题。
从技术上说,从消息队列中清除鼠标单击是可能的。但是做起来很丑,它需要点赞。我会毫不犹豫地发布替代方案,不要以为这通常是个好策略。您需要阅读this post才能了解为什么DoEvents()是危险的方法。
private void button1_Click(object sender, EventArgs e) {
button1.Enabled = false;
button1.Update();
'' long running code
''...
Application.DoEvents();
if (!button1.IsDisposed) button1.Enabled = true;
}
Update()调用可确保用户获得所需的反馈,即他需要知道反复按一下按钮不会做任何有用的事情。 DoEvents()调用将调度所有排队的鼠标单击,由于按钮仍处于禁用状态,因此它们不会发生任何事情。 IsDisposed测试对于解决DoEvents()的问题至关重要,它可以确保在代码运行时用户单击窗口的“关闭”按钮时,程序不会崩溃。
使用this post中的HourGlass类可提供更多反馈。
关于c# - 在第一次调用完成事件句柄之前,如何防止任何按钮单击事件排队,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30894162/