Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. button click event

button click event

Scheduled Pinned Locked Moved C#
designhelp
12 Posts 7 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    gaby2r
    wrote on last edited by
    #1

    lets say i have a simple form with a button on it. let button1_Click() be the function binded by the eventhandler delegate. the problem: i need this function to do a certain task that may take some time. i don't want this to freeze the UI(user interface) however i need to stop any further calls to button1_Click() for the duration of the task. sounds realy easy but to my surprise it's not that easy. take the following examples of the button1_Click function bodys: { this.button1.Enabled=false; //do task this.button1.Enabled=true; } visualy disables the button but if you push it (even if disabled) X times the function will execute exactely X times. { if(this.ignore) return; this.ignore=true; //do task this.ignore=false; } same as above just that it doesn't visualy disable the button. ideas, solutions and explanations apreciated.

    P E A 3 Replies Last reply
    0
    • G gaby2r

      lets say i have a simple form with a button on it. let button1_Click() be the function binded by the eventhandler delegate. the problem: i need this function to do a certain task that may take some time. i don't want this to freeze the UI(user interface) however i need to stop any further calls to button1_Click() for the duration of the task. sounds realy easy but to my surprise it's not that easy. take the following examples of the button1_Click function bodys: { this.button1.Enabled=false; //do task this.button1.Enabled=true; } visualy disables the button but if you push it (even if disabled) X times the function will execute exactely X times. { if(this.ignore) return; this.ignore=true; //do task this.ignore=false; } same as above just that it doesn't visualy disable the button. ideas, solutions and explanations apreciated.

      P Offline
      P Offline
      Polis Pilavas
      wrote on last edited by
      #2

      I think you should consider porting the task you wish to do on a separate thread. This will not "freeze" your GUI since it will be running on a separate thread, other than the main (GUI) one. By doing this, you could also specify that you wish to wait for your thread-processing to complete before executing the rest of your code. If you haven't implemented multiple threads before, then may I suggest to Google it. A simple google search for something like "C# Thread tutorial" or "C# Multithreading" will bring up tons of results. Hope this helps Regards, Polis Can you practice what you teach?

      A 1 Reply Last reply
      0
      • P Polis Pilavas

        I think you should consider porting the task you wish to do on a separate thread. This will not "freeze" your GUI since it will be running on a separate thread, other than the main (GUI) one. By doing this, you could also specify that you wish to wait for your thread-processing to complete before executing the rest of your code. If you haven't implemented multiple threads before, then may I suggest to Google it. A simple google search for something like "C# Thread tutorial" or "C# Multithreading" will bring up tons of results. Hope this helps Regards, Polis Can you practice what you teach?

        A Offline
        A Offline
        Anonymous
        wrote on last edited by
        #3

        the problem is not the freeze of the GUI. that i can simply avoid by multithreading as you pointed out. the issue is stopping any further calls of the function during the execution of the task. i have run into this problem when i had a task that needs like about 500 miliseconds to run (more exactely it's a MoveNext). i decided not to multythread it since it's quite short. the problem is when a users starts pounding the NextButton with 20 clicks a second (it happend to my by accident in a test) the application starts to slow down since it's ordered to do like 20 tasks/second and it can only do 2/second. not to mention sometimes it has to acces sensible data that has to be locked down for thread safety purposes and it sometimes takes like 2-5 minutes for it to actualy recover. there are more issues here like race conditions and so forth. now i thought that blocking any calls to the function would be the easyest way to do it. however it turned out not to be.

        S 1 Reply Last reply
        0
        • A Anonymous

          the problem is not the freeze of the GUI. that i can simply avoid by multithreading as you pointed out. the issue is stopping any further calls of the function during the execution of the task. i have run into this problem when i had a task that needs like about 500 miliseconds to run (more exactely it's a MoveNext). i decided not to multythread it since it's quite short. the problem is when a users starts pounding the NextButton with 20 clicks a second (it happend to my by accident in a test) the application starts to slow down since it's ordered to do like 20 tasks/second and it can only do 2/second. not to mention sometimes it has to acces sensible data that has to be locked down for thread safety purposes and it sometimes takes like 2-5 minutes for it to actualy recover. there are more issues here like race conditions and so forth. now i thought that blocking any calls to the function would be the easyest way to do it. however it turned out not to be.

          S Offline
          S Offline
          S Senthil Kumar
          wrote on last edited by
          #4

          Why don't you simply disable the button and enable it after the operation completes? Something like

          private void buttonClick(object sender, EventArgs e)
          {
          thisButton.Enabled = false;
          DoLongOperation();
          thisButton.Enabled = true;
          }

          If you can't enable/disable, you can have a flag to simulate it, set the flag to false before the operation and reset it after the operation. The function would then first check if the flag is true before proceeding. Regards Senthil _____________________________ My Blog | My Articles | WinMacro

          G 1 Reply Last reply
          0
          • S S Senthil Kumar

            Why don't you simply disable the button and enable it after the operation completes? Something like

            private void buttonClick(object sender, EventArgs e)
            {
            thisButton.Enabled = false;
            DoLongOperation();
            thisButton.Enabled = true;
            }

            If you can't enable/disable, you can have a flag to simulate it, set the flag to false before the operation and reset it after the operation. The function would then first check if the flag is true before proceeding. Regards Senthil _____________________________ My Blog | My Articles | WinMacro

            G Offline
            G Offline
            gaby2r
            wrote on last edited by
            #5

            obviously you haven't payed attention to my first post. the first example does just that. disabling the button and enabling it after the task is done. however it doesn't behave as expected. Visualy the button is disabled, but the function executes as many times as you push the button, regardless of it's state (disabled/enabled). if you put a counter in it and look at it after the test you'll see it's nice and neat the number of clicks you made. i think that this is because somehow it stacks the events and fires them after the function executes. try and run this code: public void task() { Thread.Sleep(1000); this.counter++; } private void button1_Click(object sender, System.EventArgs e) { this.button1.Enabled=false; Thread t=new Thread(new ThreadStart(task)); t.Start(); while((t.ThreadState & (System.Threading.ThreadState.Stopped | System.Threading.ThreadState.Unstarted)) == 0) { Thread.Sleep(100); } t.Join(); this.button1.Enabled=true; Debug.WriteLine(this.counter); } this has multi threading too. i can't exclude the possibility i'm doing something wrong but i can't seem to see where. pointers anyone?

            S 1 Reply Last reply
            0
            • G gaby2r

              lets say i have a simple form with a button on it. let button1_Click() be the function binded by the eventhandler delegate. the problem: i need this function to do a certain task that may take some time. i don't want this to freeze the UI(user interface) however i need to stop any further calls to button1_Click() for the duration of the task. sounds realy easy but to my surprise it's not that easy. take the following examples of the button1_Click function bodys: { this.button1.Enabled=false; //do task this.button1.Enabled=true; } visualy disables the button but if you push it (even if disabled) X times the function will execute exactely X times. { if(this.ignore) return; this.ignore=true; //do task this.ignore=false; } same as above just that it doesn't visualy disable the button. ideas, solutions and explanations apreciated.

              E Offline
              E Offline
              Enishi
              wrote on last edited by
              #6

              put this as a class variable private ThreadStart ts= new ThreadStart(urfunctionhere); private Thread t=new Thread(ts); then in ur button u could do { button.enabled=false; if(t!=null&&!(t.isAlive)) //this will check if the user hits the button when ur function is runing -- if the thread its stopped will start-- { t.start(); } button.enabled=true; } hope this help u

              G 1 Reply Last reply
              0
              • E Enishi

                put this as a class variable private ThreadStart ts= new ThreadStart(urfunctionhere); private Thread t=new Thread(ts); then in ur button u could do { button.enabled=false; if(t!=null&&!(t.isAlive)) //this will check if the user hits the button when ur function is runing -- if the thread its stopped will start-- { t.start(); } button.enabled=true; } hope this help u

                G Offline
                G Offline
                gaby2r
                wrote on last edited by
                #7

                well for one your example doesn't work. mainly because that's not the propper way to test if a thread is running. however even if i correct that problem it still doesn't solve my problem because now you have to sincronize the started thread. if you will read my third post you'll see a sincronised example that well you guessed it .. doesn't stop the calls.

                1 Reply Last reply
                0
                • G gaby2r

                  lets say i have a simple form with a button on it. let button1_Click() be the function binded by the eventhandler delegate. the problem: i need this function to do a certain task that may take some time. i don't want this to freeze the UI(user interface) however i need to stop any further calls to button1_Click() for the duration of the task. sounds realy easy but to my surprise it's not that easy. take the following examples of the button1_Click function bodys: { this.button1.Enabled=false; //do task this.button1.Enabled=true; } visualy disables the button but if you push it (even if disabled) X times the function will execute exactely X times. { if(this.ignore) return; this.ignore=true; //do task this.ignore=false; } same as above just that it doesn't visualy disable the button. ideas, solutions and explanations apreciated.

                  A Offline
                  A Offline
                  Ashok Dhamija
                  wrote on last edited by
                  #8

                  You may try the following method if it works (it apparently works on my machine; however I cannot test in your conditions). As an event can be handled by more than one event handler, you may declare two event handlers for the same button click by using two different methods, as under:

                  this.button1.Click += new System.EventHandler(this.button1_Click);
                  this.button1.Click += new System.EventHandler(this.button1_Click2);

                  It is pertinent to mention here that when an event is handled by more than one handler, all the methods handling that event are executed. The order in which the methods execute is the same as the order in which the association was created. Thus, in this case, "button1_Click" method will be executed first and thereafter the second method "button1_Click2" will be executed. What I suggest it that you disable the button1 in the first such method and do your long task in the second method. As by the time the second method starts, the first method must already have been executed (meaning that the button1 is now already disabled), you can safely do your long task in the second method. The code can be something like this:

                  private void button1_Click(object sender, System.EventArgs e)
                  {
                  this.button1.Enabled = false;
                  }

                  private void button1_Click2(object sender, System.EventArgs e)
                  {
                  //do the long task here

                      //After finishing the long task, re-enable button1
                      this.button1.Enabled = true;
                  

                  }

                  I am not sure, but I hope that your problem can be solved in this manner.

                  1 Reply Last reply
                  0
                  • G gaby2r

                    obviously you haven't payed attention to my first post. the first example does just that. disabling the button and enabling it after the task is done. however it doesn't behave as expected. Visualy the button is disabled, but the function executes as many times as you push the button, regardless of it's state (disabled/enabled). if you put a counter in it and look at it after the test you'll see it's nice and neat the number of clicks you made. i think that this is because somehow it stacks the events and fires them after the function executes. try and run this code: public void task() { Thread.Sleep(1000); this.counter++; } private void button1_Click(object sender, System.EventArgs e) { this.button1.Enabled=false; Thread t=new Thread(new ThreadStart(task)); t.Start(); while((t.ThreadState & (System.Threading.ThreadState.Stopped | System.Threading.ThreadState.Unstarted)) == 0) { Thread.Sleep(100); } t.Join(); this.button1.Enabled=true; Debug.WriteLine(this.counter); } this has multi threading too. i can't exclude the possibility i'm doing something wrong but i can't seem to see where. pointers anyone?

                    S Offline
                    S Offline
                    S Senthil Kumar
                    wrote on last edited by
                    #9

                    Yeah, you're right. What's happening is after the button gets disabled, all the clicks keep getting added to the message queue and once your button gets enabled, they get dispatched to the button and so you keep getting the event as many times as the user clicked. To prevent that from happening, just call Application.DoEvents() before enabling the button. That'll clear off all those click messages in the queue and therefore you wont get the Click event. Just do

                    public void task()
                    {
                    Thread.Sleep(1000);
                    this.counter++;
                    }
                    private void button1_Click(object sender, System.EventArgs e)
                    {
                    this.button1.Enabled=false;
                    Thread t=new Thread(new ThreadStart(task));
                    t.Start();
                    while((t.ThreadState & (System.Threading.ThreadState.Stopped | System.Threading.ThreadState.Unstarted)) == 0)
                    {
                    Thread.Sleep(100);
                    }
                    t.Join();

                    Application.DoEvents(); // This is the only change.

                    this.button1.Enabled=true;
                    Debug.WriteLine(this.counter);
                    }

                    Regards Senthil _____________________________ My Blog | My Articles | WinMacro

                    G 1 Reply Last reply
                    0
                    • S S Senthil Kumar

                      Yeah, you're right. What's happening is after the button gets disabled, all the clicks keep getting added to the message queue and once your button gets enabled, they get dispatched to the button and so you keep getting the event as many times as the user clicked. To prevent that from happening, just call Application.DoEvents() before enabling the button. That'll clear off all those click messages in the queue and therefore you wont get the Click event. Just do

                      public void task()
                      {
                      Thread.Sleep(1000);
                      this.counter++;
                      }
                      private void button1_Click(object sender, System.EventArgs e)
                      {
                      this.button1.Enabled=false;
                      Thread t=new Thread(new ThreadStart(task));
                      t.Start();
                      while((t.ThreadState & (System.Threading.ThreadState.Stopped | System.Threading.ThreadState.Unstarted)) == 0)
                      {
                      Thread.Sleep(100);
                      }
                      t.Join();

                      Application.DoEvents(); // This is the only change.

                      this.button1.Enabled=true;
                      Debug.WriteLine(this.counter);
                      }

                      Regards Senthil _____________________________ My Blog | My Articles | WinMacro

                      G Offline
                      G Offline
                      gaby2r
                      wrote on last edited by
                      #10

                      neat! works. thanks for the help

                      P 1 Reply Last reply
                      0
                      • G gaby2r

                        neat! works. thanks for the help

                        P Offline
                        P Offline
                        Pete OHanlon
                        wrote on last edited by
                        #11

                        Alternatively, you could just decouple the event handler and then recouple it after the call.

                        G 1 Reply Last reply
                        0
                        • P Pete OHanlon

                          Alternatively, you could just decouple the event handler and then recouple it after the call.

                          G Offline
                          G Offline
                          gaby2r
                          wrote on last edited by
                          #12

                          yeah that crossed my mind too. but it seems a bit sadistic to me anyways. funny thing is i knew about Application.DoEvents() and actualy used it .. but to no result. in my test i placed it in the while loop because normaly you want from time to time the app to respond to other calls but oddly it didn't work(no idea why thow). the other thing that crossed my mind was to add a messageFilter before thread.Start and remove it after my task finished. but that's a bit too costly in my opinion.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups