Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 禁用按钮时出现奇怪问题_C#_.net_Winforms - Fatal编程技术网

C# 禁用按钮时出现奇怪问题

C# 禁用按钮时出现奇怪问题,c#,.net,winforms,C#,.net,Winforms,我有一个WinForm,里面有一个按钮。在按钮的click事件中,我调用button1.Enabled=false,然后接下来是许多行代码。在这个代码之后,我调用button1.Enabled=true 这样做是为了在执行过程中不能按下按钮。奇怪的是,当按钮被禁用时,如果用户多次单击按钮,按钮实际上被单击了 有人能解释为什么会发生这种情况吗?代码如下所示: button1.Enabled = false //Code //Code //Code button1.Enabled = true 我

我有一个WinForm,里面有一个按钮。在按钮的click事件中,我调用
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只会在应用程序上触发排队事件(在本例中为按钮按下事件)。经验法则是,在单独的线程中执行任何耗时的任务。感谢所有人的帮助-非常感谢!感谢您的帮助-非常感谢!感谢您的帮助-非常感谢!