1

I have a button click event handler with a switch case in it that controls multiple buttons in one event handler.

I need to use a queue because while one button is clicked and doing some processing, second button click won't interfere with the first button click, but added to the queue. I don't want to use .enabled=false; because it'll discard the second click completely, and I'm currently editing someone's software at work so I don't want to break things that I don't know, so what are you suggesting?

Taha Paksu
  • 15,371
  • 2
  • 44
  • 78
  • This may not be necessary if the event handlers run on the UI thread. If every operation is handled on the same thread then the first operation will block all subsequent clicks from getting processed. – Alex Essilfie Jun 19 '12 at 09:01

3 Answers3

1

The best idea, I think, is to create a producer/consumer queue.

Another question is explaining this technique.

Basically, the idea is to have a worker thread that will consume a queue to get the job to do, while other thread produce job by queuing operation in the queue.

Community
  • 1
  • 1
Steve B
  • 36,818
  • 21
  • 101
  • 174
  • How can I use it with a button_click event? I'm not much qualified at working threads so any example would be good. – Taha Paksu Jun 19 '12 at 07:39
  • Here can be a good starting point : http://stackoverflow.com/a/5108487/588868. The challenge when using threading in windows forms apps is to avoid accessing controls properties not in the UI thread. You'll need a bunch of anyControl.InvokeRequired and anyControl.Invoke to execute code in the UI thread. – Steve B Jun 19 '12 at 07:45
  • basically, I was thinking something like setting a flag for process (isProcessing=true/false) and checking it when user clicks one of the buttons, then if processing add this button click event to queue then execute the queue while it's not empty. But I need a way to queue the button_click. or add the button to the queue then invoke the click event. I'll try that first. – Taha Paksu Jun 19 '12 at 07:53
  • how do you write your click event today ? you are probably already using some threading technic, aren't you ? – Steve B Jun 19 '12 at 07:55
  • The problem is, I didn't write it :) It's a standard c# click event with this inside it : `uCtrlButton btn = ((uCtrlButton)kontrol); if (btn != null && btn.Tag != null) { switch (Convert.ToByte(btn.Tag.ToString())) {` etc. – Taha Paksu Jun 19 '12 at 08:02
  • ok, but how do you call the processing itself? if you don't process in another thread, the UI will be blocked until the process is finished. according your description, the UI is not blocked. – Steve B Jun 19 '12 at 08:04
  • It might be inside the usercontrol cause I don't see any threads. But as you say, UI isn't blocked. – Taha Paksu Jun 19 '12 at 08:06
0

I did succeed this with System.Collections.Queue

The code is :

private Queue<Button> Button_Queue = new Queue<Button>();
private bool isProcessing = false;

private void Button_Click((object sender, EventArgs e){

if(isProcessing){
    Button_Queue.Enqueue(this);
}
else
{
    isProcessing = true;

    // code here

    isProcessing = false;
    while(Button_Queue.Count > 0){
        Button_Queue.Dequeue().PerformClick();
    }
}

of course mine is slightly different from this because I need to pass some variables and my click method is modified for this.

Taha Paksu
  • 15,371
  • 2
  • 44
  • 78
0

Dirty, but simple solution.

public partial class DataRefresh : Form //DataRefresh is just "some form"   
   {
      ...
      ...
        
      public DateTime ClickTime; //Time when click is processed by system  
      public DateTime LastExecutionRunTime = DateTime.MinValue; //Time when the all the click code finish
        
      private void buttonDataRefresh_Click(object sender, EventArgs e)
         {
            ClickTime = DateTime.Now;
            if (ClickTime.Subtract(LastExecutionRunTime).TotalSeconds < 5 ) 
            {
               //It will keep returning - hopefully until all events in que are satisfied  
               return;
            }

            //Long running code
            //Importing whole table from remote DB
            ...
            ...
            //End of the Long running code 
            
            LastExecutionRunTime = DateTime.Now;
         }
   }
Pepik
  • 111
  • 1
  • 6
  • 1
    This is called "debouncing" technique, which will prevent the button to be clicked multiple times, which doesn't seem to answer the question. Thanks for the effort though. The main idea is not to lose the second click, instead adding it to a queue and executing it after the first click finishes. Three clicks, three consequent executions without overlaps. – Taha Paksu Sep 07 '21 at 20:10