tags:

views:

31

answers:

1

I have a problem that I'd like some advice on. I have a button in my GUI that starts a complicated setup sequence (to connect to a analogue to digital converter and start logging data from an echo sounder). Once it is finished setting up, the button changes from START to STOP and has the expected behaviour. What I was experiencing is that during the long operation, if the user clicked on the button again (even though it was disabled) the event would still be sent to the button once it was reenabled. The only way I've found to make this work properly is to call Application.DoEvents() before enabling the button again. All I really want to do is swallow up the events destined for my button, so DoEvents() seems a bit heavy handed. Since people seem to be unanimously against calling DoEvents() I'm hoping that the bright minds here can help me come up with an alternative solution. Note I haven't tried my demo code but it follows my real code closely, excepting the really long methods.

  1. Is there an alternative way to accomplish this?
  2. Is it safe(ish) to call DoEvents() from the completion portion of the background worker?

    public class Form1 : Form {

    BackgroundWorker worker;
    Button startButton;
    bool state;
    
    
    public Form1() {
        state = false;
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(StartSequence);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ToggleButton);
        startButton = new Button();
        startButton.Text = "START";
        startButton.Click += new System.EventHandler(StartClicked);
        this.Controls.Add(startButton);
    }
    
    
    private void StartClicked( object sender, EventArgs e ) {
        startButton.Enabled = false;
        worker.RunWorkerAsync( !state );
    }
    
    
    private void StartSequence( object sender, DoWorkEventArgs e ) {
        bool onState = (bool) e.Argument;
        if ( onState ) {
            RunReallyLongStartupSequence();
        }
        else {
            RunReallyLongStopSequence();
        }
        state = onState;
    }
    
    
    private void ToggleButton( object sender, RunWorkerCompletedEventArgs e ) {
        startButton.Text = state ? "STOP" : "START";
    
    
    
    // THIS IS WHAT I AM WORRIED ABOUT!
    Application.DoEvents();
    startButton.Enabled = true;
    
    }

    }

A: 

Application.DoEvents() isn't heavy-handed, and I don't think programmers are unanimously opposed to DoEvents in all cases. DoEvents has a bad reputation because it has traditionally been used as a magical hack fix for badly-written code. In your case, it is the proper and normal way to deal with your situation.

In Windows, the situation you describe (where clicks on disabled buttons are applied when the buttons are re-enabled) is actually normal, expected behavior for a control. However, this does not mean that it is always desirable behavior from a programmer's standpoint, and if you have users that are prone to clicking away on disabled buttons, then the simplest way is to use DoEvents, which is nothing more than a method telling the form to go ahead and process any events it has queued up. Use it proudly!

MusiGenesis