Click to See Complete Forum and Search --> : How to prevent multiple button click?
john_avi
July 6th, 2009, 01:07 AM
I have a form which has a button(sychronize all). I do some process when clicked on this button and disable it when clicked on. To disable it I have used the following code:
buttonSyncAll.Enabled = false;
this.Update();
When I click on this button it gets disabled and process starts.if I click on this button when it is disabled nothing happens unless process finished but once the process is finished it starts again. So somewhere application is keeping click event in queue and implementing it after it has finished the earlier event. Please tell me how can I make sure that until process finishes, the click event should not be saved/stored. I want that click event should only be handled when button gets enabled again.
BigEd781
July 6th, 2009, 01:22 AM
I am pretty sure that Click messages are sent when the button is disabled, so I would look for any other reasons this may be happening. For a hack fix you could always unsubscribe from the event at the top of the handler and subscribe again when the method completes, but this should not be necessary.
john_avi
July 6th, 2009, 01:53 AM
I dont know how to do it.can you please tell me exactly how it can be done? I am new to C# programming. I have added event using visual studio IDE.
this.buttonSyncAll.Click += new System.EventHandler(this.OnClickSyncAll);
BigEd781
July 6th, 2009, 02:07 AM
this.buttonSyncAll.Click -= this.OnClickSyncAll;
"-=" instead of "+=", but again, I don't think it is a good solution.
foamy
July 6th, 2009, 05:50 AM
If the process that is started on the click event runs in the main/UI thread, your application will "hang". This means that the second click isn't processed by the form until the process completes and the button is re-activated.
Shuja Ali
July 6th, 2009, 01:24 PM
I will second with that. :)
You should actually re-look at how you are doing this process. May be doing it with the help of BackgroundWorker component would be nice.
Arjay
July 6th, 2009, 04:49 PM
+3
If you really need to only perform the operation once, you'll need to start a separate thread. I've tried a few variations, including disabling the button and event and creating a guard block.
All are ineffective if the button has focus and the user rapidly clicks twice.
Test code.
private void buttonClicky_Click( object sender, EventArgs e )
{
Application.DoEvents( );
if( !_inClickyMethod )
{
_inClickyMethod = true;
// buttonClicky.Click -= new EventHandler( buttonClicky_Click );
buttonClicky.Enabled = false;
System.Threading.Thread.Sleep( 5000 );
Debug.WriteLine( "Clicky" );
buttonClicky.Enabled = true;
_inClickyMethod = false;
// buttonClicky.Click += new EventHandler( buttonClicky_Click );
}
john_avi
July 7th, 2009, 12:34 AM
I also tried to take the focus away from the button but it is of no use. it starts acting on the click event only once it is finished with the earlier click event so every solution seems to fail. I don't know why it is so. in MFC if you disable a button it does not receive any event. So behavior of buttons seems very strange is c#.
BigEd781
July 7th, 2009, 12:40 AM
You do not get click events when buttons are enabled, really, you don't. You must be clicking fast enough to push two messages onto the queue. Just take the others advice and do what you need to do in a separate thread.
john_avi
July 7th, 2009, 04:04 AM
thanks to all of you. I changed the code to use a separate thread. But still I am surprised that this feature has already been implemented it MFC then why it is not in C# .net.
BigEd781
July 7th, 2009, 12:20 PM
thanks to all of you. I changed the code to use a separate thread. But still I am surprised that this feature has already been implemented it MFC then why it is not in C# .net.
What? What "feature"? Disabled buttons do not fire Click events. Seriously, they don't.
Shuja Ali
July 7th, 2009, 01:24 PM
Actually BigEd, the problem has been misunderstood. You are right disabled buttons do not fire click events, but in this case, as the control does not return back to the form, the button stays enabled because of the long process that is running in the button's click event handler. This is a problem with the code and not with .NET framework or C#.
Arjay
July 7th, 2009, 01:59 PM
Shula, I respectfully disagree.
From the test code I posted (in one of several variations), I believe the click requests are getting queued up as BigEd proposed.
For my tests, I made sure the button in question had focus and then I rapidly double clicked on it.
Here's the sequence:
Button disabled
Pause for 5 seconds (due to Sleep statement)
Debug.Writeline "Clicky" appeared in the output window
(2nd click event processed)
Pause for 5 seconds
Debug.Writeline "Clicky" appeared in the output window
Button enabled
When the button is rapidly clicked, the two button events are getting queued before the button is initially disabled.
Shuja Ali
July 7th, 2009, 02:20 PM
I didn't see your code. You are using Application.DoEvents(), why is that? What happens when you remove this statement?
Arjay
July 7th, 2009, 04:07 PM
I didn't see your code. You are using Application.DoEvents(), why is that? What happens when you remove this statement?I tried it all sorts of ways - the way I posted was just one of the tests. None matter.
Test 1
private void buttonClicky_Click( object sender, EventArgs e )
{
buttonClicky.Enabled = false;
System.Threading.Thread.Sleep( 5000 );
Debug.WriteLine( "Clicky" );
buttonClicky.Enabled = true;
}
Test 2
private void buttonClicky_Click( object sender, EventArgs e )
{
buttonClicky.Click -= new EventHandler( buttonClicky_Click );
buttonClicky.Enabled = false;
System.Threading.Thread.Sleep( 5000 );
Debug.WriteLine( "Clicky" );
buttonClicky.Enabled = true;
buttonClicky.Click += new EventHandler( buttonClicky_Click );
}
Test 3
private void buttonClicky_Click( object sender, EventArgs e )
{
buttonClicky.Enabled = false;
buttonClicky.Click -= new EventHandler( buttonClicky_Click );
System.Threading.Thread.Sleep( 5000 );
Debug.WriteLine( "Clicky" );
buttonClicky.Click += new EventHandler( buttonClicky_Click );
buttonClicky.Enabled = true;
}
Test 4
private void buttonClicky_Click( object sender, EventArgs e )
{
buttonClicky.Enabled = false;
buttonClicky.Click -= new EventHandler( buttonClicky_Click );
Application.DoEvents( );
System.Threading.Thread.Sleep( 5000 );
Debug.WriteLine( "Clicky" );
buttonClicky.Click += new EventHandler( buttonClicky_Click );
buttonClicky.Enabled = true;
}
Test 5
private void buttonClicky_Click( object sender, EventArgs e )
{
if( !_inClickyMethod )
{
_inClickyMethod = true;
buttonClicky.Click -= new EventHandler( buttonClicky_Click );
buttonClicky.Enabled = false;
System.Threading.Thread.Sleep( 5000 );
Debug.WriteLine( "Clicky" );
buttonClicky.Enabled = true;
_inClickyMethod = false;
buttonClicky.Click += new EventHandler( buttonClicky_Click );
}
}
Test 6
private void buttonClicky_Click( object sender, EventArgs e )
{
Application.DoEvents( );
if( !_inClickyMethod )
{
_inClickyMethod = true;
buttonClicky.Enabled = false;
System.Threading.Thread.Sleep( 5000 );
Debug.WriteLine( "Clicky" );
buttonClicky.Enabled = true;
_inClickyMethod = false;
}
}
.and maybe a few others.
Shuja Ali
July 8th, 2009, 02:44 PM
Ok. I got the point now. The default behavior of windows is that it queues up events as messages. Now when you click a button, in the event handler we first make the button disabled and then start some process, the UI is locked. In the mean time, you try to click the disabled button, this click gets queued up and when the button is enabled and the UI is unlocked, the event gets first and it again triggers the click event. Why only Button, you can try it with any control on the form. Actually using same code, you will see that when you run the code and click the button and then immediately click the minimize button on the form and you will see once the event handler completed, the form would be minimized.
The way I would do is disable the button, start a process on the another thread and once that work is complete enable the button in the "RunWorkerCompleted " event handler of the background worker.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.