Preventing multiple button clicks and process recursion
-
When using a button on a form to launch a process. How can I prevent unintentional recursion. If you do fast multiple clicks of the button it runs the process multiple times. I have tried disabling the button on Form1 while running the process. It appears that multiple events are queued in the message queue before running the process. Thanks Steve
-
When using a button on a form to launch a process. How can I prevent unintentional recursion. If you do fast multiple clicks of the button it runs the process multiple times. I have tried disabling the button on Form1 while running the process. It appears that multiple events are queued in the message queue before running the process. Thanks Steve
An easy solution for your problem is to keep a flag for the process to start.ie when ever you see the flag true do not initiate the process.On your button click set this flag to true and at the end of the process set it back to false.Check the status of this flag before initiating the process. James Poulose
-
An easy solution for your problem is to keep a flag for the process to start.ie when ever you see the flag true do not initiate the process.On your button click set this flag to true and at the end of the process set it back to false.Check the status of this flag before initiating the process. James Poulose
I was about to post this when I read your reply. Decided to go ahead and post anyway. /// message Assuming you've assigned an EventHandler delegate from a private method on the Form to handle the Button's Click event, could you set a private flag, and test its value before launching the Process? Something like the pseudo-code below, so you can ignore the Button.Enabled property? (and so the Button doesn't have to know anything about the Process or the Form?)
private void HandleButtonClick(object sender, EventArgs e){
// at the beginning
if (!this.canLaunch) return;
// set the flag before launch
this.canLaunch = false;
Process targetProcess = new Process();
// set EnableRaisingEvents
targetProcess.EnableRaisingEvents = true;
// assign exit event handler
targetProcess.Exited += new EventHandler(this.TargetEnded);
targetProcess.Start(...);
}
// process.Exited handler
private void TargetEnded (object sender, EventArgs e){
this.canLaunch = true;
}
// if other objects need to know:
public bool LaunchEnabled {
get { return this.canLaunch; }
}
HTH JSF
-
I was about to post this when I read your reply. Decided to go ahead and post anyway. /// message Assuming you've assigned an EventHandler delegate from a private method on the Form to handle the Button's Click event, could you set a private flag, and test its value before launching the Process? Something like the pseudo-code below, so you can ignore the Button.Enabled property? (and so the Button doesn't have to know anything about the Process or the Form?)
private void HandleButtonClick(object sender, EventArgs e){
// at the beginning
if (!this.canLaunch) return;
// set the flag before launch
this.canLaunch = false;
Process targetProcess = new Process();
// set EnableRaisingEvents
targetProcess.EnableRaisingEvents = true;
// assign exit event handler
targetProcess.Exited += new EventHandler(this.TargetEnded);
targetProcess.Start(...);
}
// process.Exited handler
private void TargetEnded (object sender, EventArgs e){
this.canLaunch = true;
}
// if other objects need to know:
public bool LaunchEnabled {
get { return this.canLaunch; }
}
HTH JSF
The following code does not prevent a fast double click on the button and it still runs multiple times. I used a textbox to display the count of the number of times the process is executed. #region Using directives using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Windows.Forms; #endregion namespace ClickMe { partial class Form1 : Form { public int counter = 0; public canLaunch Busy = new canLaunch(); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { if (!this.Busy.can_Launch) { this.Busy.can_Launch = true; this.button1.Enabled = false; for (long i = 0; i < 100000000; i++) ; counter++; this.textBox1.Text = counter.ToString(); this.Busy.can_Launch = false; this.button1.Enabled = true; } } } public class canLaunch { private static bool busy = false; public canLaunch() { } public bool can_Launch { get { return busy; } set { busy = value; } } } }