How to prevent any button press event from the queue until the event descriptor completes with the first call

I want to prevent a button from being pressed in the queue. In testing, I have a form, a button and in the code behind. I have an event handler:

private void button1_Click(object sender, EventArgs e) { if (_codeRunning) return; _codeRunning = true; //Application.DoEvents(); //button1.Enabled = false; _click ++; Debug.WriteLine("Click Number: " + _click); Task.Delay(5000).Wait(); //button1.Enabled = true; _codeRunning = false; } 

When I run debug and click on the button twice, three, or four times faster, Debug Output shows each click about five seconds after the last one. I would like for him to show one click and leave the rest until the first event ends.

I also tried disabling the button, as well as temporarily removing the handler from the Button_click event. These are all the same results.

+5
source share
2 answers

There are various problems that you will have to face when you hang a user interface thread like this. This, of course, is one of them, nothing pleasant happens when the user wildly knocks on a button to try to achieve something noticeable. And of course, these clicks will not be lost, they will remain stored in the message queue. To activate the Click event handler again when the event handler stops working.

It is important to learn how to use the BackgroundWorker or Task classes to avoid such troubles. Just for this, just set the Enabled property.

Clearing mouse clicks from the message queue is technically possible. But ugly to do, it requires pinvoke. I hesitantly publish an alternative, do not think that this is generally a good strategy. You will need to read this post to get an idea of โ€‹โ€‹why DoEvents () is a dangerous method.

  private void button1_Click(object sender, EventArgs e) { button1.Enabled = false; button1.Update(); '' long running code ''... Application.DoEvents(); if (!button1.IsDisposed) button1.Enabled = true; } 

Calling Update () ensures that the user receives feedback that he needs to know that repeatedly pressing the button will not bring anything useful. In the DoEvents () call, all mouse clicks in the queue will be sent, nothing happens to them, since the button is still disabled. The IsDisposed test is necessary to solve the problem with DoEvents (), this ensures that your program does not work when the user clicks the Close button while the code is running.

Use the HourGlass class in this post to provide more feedback.

+7
source

I had a button that was going to launch a method on the click event. The same problem occurs, and when the user clicked several times, the method was launched several times. Therefore, I made a boolean and changed its value when the method started.

private bool IsTaskRunning = false

 private void MyMethod(){ if(IsTaskRunning==false){ IsTaskRunning=true; //My heavy duty code that takes a long time IsTaskRunning=false; //When method is finished } } 

So, now the method runs only if it was executed for the last time.

0
source

All Articles