Reputation: 4897
I've got a WinForm, which contains a button. In the button's click event, I call button1.Enabled = false
and then a number of lines of code follow. After this code, I call button1.Enabled = true
.
This is done so that the button cannot be pressed while the execution is being carried out. The strange thing is that while the button is disabled, if the user clicks on the button many times, the button is actually clicked.
Could anyone explain why this is happening? The code looks like this:
button1.Enabled = false
//Code
//Code
//Code
button1.Enabled = true
Upvotes: 2
Views: 2189
Reputation: 21
I solved this using Application.DoEvents() to empty the queue before re enabling the button
AppButton.Enabled = false;
...
do some work
...
Application.DoEvents();
AppButton.Enable = true;
Upvotes: 2
Reputation: 1500375
My guess is that you're actually doing a load of work in those lines of code, blocking the UI thread. You shouldn't do that - you should set the button to be disabled, then start off your work in a background thread (or using asynchronous calls, if most of the time is spent talking to a web service or something similar). Then when the work is finished, it should marshal a call back into the UI thread to re-enable the button.
(If that's not the problem, please show a short but complete program which demonstrates the problem.)
EDIT: Thanks to Sarwar's comments, I understand why you're getting the multiple events being fired - they're being queued up (due to the UI thread being blocked), and only processed after the button is re-enabled. So yes, if you avoid doing lots of work on the UI thread, it can handle the clicks on the disabled button, ignore them, and then there won't be a backlog when the button is re-enabled.
EDIT: For anyone who is interested in trying this themselves, here's my test program demonstrating the problem:
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");
}
}
And the fix using C# 5's async handling:
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");
}
Upvotes: 5
Reputation: 12906
We encountered this same problem and like Jon mentioned, it was because the UI was blocked by the work we did inside the click event. When the UI resumed, it registered all the clicks which had happened when the UI was blocked.
Here's an another answer from Stack Overflow which provides some code showing how you can fix the problem.
Upvotes: 1