我有一个WinForm,其中包含一个按钮.在按钮的单击事件中,我调用button1.Enabled = false然后跟随多行代码.在这段代码之后,我打电话给button1.Enabled = true.
这样做是为了在执行执行时不能按下按钮.奇怪的是,当按钮被禁用时,如果用户多次点击该按钮,则实际上会点击该按钮.
任何人都可以解释为什么会这样吗?代码如下所示:
button1.Enabled = false
//Code
//Code
//Code
button1.Enabled = true
Run Code Online (Sandbox Code Playgroud)
我的猜测是你实际上在这些代码行中做了很多工作,阻塞了UI线程.您不应该这样做 - 您应该将按钮设置为禁用,然后在后台线程中开始工作(或者使用异步调用,如果大部分时间花在与Web服务或类似的东西上进行交谈).然后,当工作完成时,它应该将一个回调编组回UI线程以重新启用该按钮.
(如果这不是问题,请显示一个简短但完整的程序来说明问题.)
编辑:感谢Sarwar的评论,我理解为什么你要解决多个事件 - 他们正在排队(由于UI线程被阻止),并且只在重新启用按钮后才进行处理.所以是的,如果你避免在UI线程上做很多工作,它可以处理禁用按钮的点击,忽略它们,然后在重新启用按钮时不会出现积压.
编辑:对于任何有兴趣自己尝试的人,这是我的测试程序演示问题:
using System;
using System.Windows.Forms;
using System.Threading;
using System.Threading.Tasks; // For the fix below
class Program
{
static void Main()
{
Button button = new Button { Text = "Click me" };
button.Click += HandleClick;
Form form = new Form { Controls = { button } };
Application.Run(form);
}
static void HandleClick(object sender, EventArgs e)
{
Console.WriteLine("In click handler");
Button button = (Button) sender;
button.Enabled = false;
Thread.Sleep(10000);
button.Enabled = true;
Console.WriteLine("Finishing click handler");
}
}
Run Code Online (Sandbox Code Playgroud)
使用C#5的异步处理修复:
static async void HandleClick(object sender, EventArgs e)
{
Console.WriteLine("In click handler");
Button button = (Button) sender;
button.Enabled = false;
// Delay by 10 seconds, but without blocking the UI thread
await TaskEx.Delay(10000);
button.Enabled = true;
Console.WriteLine("Finishing click handler");
}
Run Code Online (Sandbox Code Playgroud)