C# 禁用按钮时出现奇怪问题
我有一个WinForm,里面有一个按钮。在按钮的click事件中,我调用C# 禁用按钮时出现奇怪问题,c#,.net,winforms,C#,.net,Winforms,我有一个WinForm,里面有一个按钮。在按钮的click事件中,我调用button1.Enabled=false,然后接下来是许多行代码。在这个代码之后,我调用button1.Enabled=true 这样做是为了在执行过程中不能按下按钮。奇怪的是,当按钮被禁用时,如果用户多次单击按钮,按钮实际上被单击了 有人能解释为什么会发生这种情况吗?代码如下所示: button1.Enabled = false //Code //Code //Code button1.Enabled = true 我
button1.Enabled=false
,然后接下来是许多行代码。在这个代码之后,我调用button1.Enabled=true
这样做是为了在执行过程中不能按下按钮。奇怪的是,当按钮被禁用时,如果用户多次单击按钮,按钮实际上被单击了
有人能解释为什么会发生这种情况吗?代码如下所示:
button1.Enabled = false
//Code
//Code
//Code
button1.Enabled = true
我的猜测是,您实际上在这些代码行中做了大量工作,阻塞了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");
}
}
以及使用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");
}
我的猜测是,您实际上在这些代码行中做了大量工作,阻塞了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");
}
}
以及使用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");
}
我们遇到了同样的问题,就像Jon提到的,这是因为我们在click事件中所做的工作阻塞了UI。当UI恢复时,它记录了UI被阻止时发生的所有单击
下面是一个示例,其中提供了一些代码,说明如何解决问题。我们遇到了同样的问题,正如Jon提到的,这是因为我们在单击事件中所做的工作阻止了UI。当UI恢复时,它记录了UI被阻止时发生的所有单击
下面是一个示例,其中提供了一些代码,说明如何解决此问题。我使用Application.DoEvents()解决了这个问题,在重新启用按钮之前清空了队列
AppButton.Enabled = false;
...
do some work
...
Application.DoEvents();
AppButton.Enable = true;
我使用Application.DoEvents()解决了这个问题,在重新启用按钮之前清空队列
AppButton.Enabled = false;
...
do some work
...
Application.DoEvents();
AppButton.Enable = true;
在设置Enabled=false后,它是否真的显示为禁用?在设置Enabled=false后,它是否真的显示为禁用?事件处理程序的可能副本使应用程序保持繁忙(或无响应),在这种情况下,Windows(操作系统,而非应用程序)所做的是将事件排队。当应用程序再次响应时(在事件处理程序中执行任务的末尾),Windows只会在应用程序上触发排队事件(在本例中为按钮按下事件)。经验法则是,在单独的线程中执行任何耗时的任务。感谢所有人的帮助-非常感谢!事件处理程序使应用程序保持忙碌(或无响应),在这种情况下,Windows(操作系统,而不是应用程序)所做的是将事件排队。当应用程序再次响应时(在事件处理程序中执行任务的末尾),Windows只会在应用程序上触发排队事件(在本例中为按钮按下事件)。经验法则是,在单独的线程中执行任何耗时的任务。感谢所有人的帮助-非常感谢!感谢您的帮助-非常感谢!感谢您的帮助-非常感谢!