在第一次调用完成事件句柄之前,如何防止任何按钮单击事件排队
How do I prevent any button click events from queuing until the event handle is finished with the first call
我想防止按钮点击排队。在测试中,我有一个表单、一个按钮,在代码隐藏中我有事件处理程序:
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 classes 来避免此类麻烦非常重要。只需将按钮设置为 Enabled 属性 即可解决此问题。
从消息队列中清除鼠标点击在技术上是可行的。但是做起来很难看,它需要 pinvoke。我会犹豫 post 替代方案,不要认为这通常是一个好的策略。您需要阅读 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() 问题至关重要,它确保当用户在代码为 运行.[=13= 时单击 window 的关闭按钮时您的程序不会崩溃]
使用 this post 中的沙漏 class 提供更多反馈。
我有一个按钮,在点击事件时会转到 运行 一个方法。同样的问题发生了,当用户点击多次时,该方法被多次触发。所以我创建了一个布尔值并在方法启动时更改了它的值。
private bool IsTaskRunning = false;
private void MyMethod()
{
if ( IsTaskRunning==false )
{
IsTaskRunning=true;
// My heavy duty code that takes a long time
IsTaskRunning=false; // When method is finished
}
}
所以现在方法 运行 只有在上次完成时才有效。
我想防止按钮点击排队。在测试中,我有一个表单、一个按钮,在代码隐藏中我有事件处理程序:
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 classes 来避免此类麻烦非常重要。只需将按钮设置为 Enabled 属性 即可解决此问题。
从消息队列中清除鼠标点击在技术上是可行的。但是做起来很难看,它需要 pinvoke。我会犹豫 post 替代方案,不要认为这通常是一个好的策略。您需要阅读 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() 问题至关重要,它确保当用户在代码为 运行.[=13= 时单击 window 的关闭按钮时您的程序不会崩溃]
使用 this post 中的沙漏 class 提供更多反馈。
我有一个按钮,在点击事件时会转到 运行 一个方法。同样的问题发生了,当用户点击多次时,该方法被多次触发。所以我创建了一个布尔值并在方法启动时更改了它的值。
private bool IsTaskRunning = false;
private void MyMethod()
{
if ( IsTaskRunning==false )
{
IsTaskRunning=true;
// My heavy duty code that takes a long time
IsTaskRunning=false; // When method is finished
}
}
所以现在方法 运行 只有在上次完成时才有效。