6

I want to make the program wait for a button to be pressed before it continues, I tried creating a while loop and having it loop until the button is clicked and sets a bool to true for the while loop to end, this made it crash

while (!Redpress)
{
    // I'd like the wait here
}

Redpress = false;

It doesn't matter whether or not the while is there, as long as the program waits for the button press before setting "Redpress" to false... Any Ideas?

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
aelsheikh
  • 2,268
  • 5
  • 26
  • 41
  • The button event is already there, I need the program to wait for the event. – aelsheikh Apr 11 '11 at 22:48
  • You cannot write code like this in a user interface thread. It will freeze the UI. Understanding the event-driven nature of UI programming is essential to get ahead. – Hans Passant Apr 11 '11 at 23:38

4 Answers4

6

Use events - it's what they're designed for.

You don't need to use a boolean variable for this in the Button_Click event handler call your code:

private void Button_Click(object sender, EventArgs e)
{
    // The code you need to execute when the button is pressed
}

As @trickdev points out you will need to subscribe to this event but if you use the Events window in Visual Studio it will add the necessary code - including the empty handler - for you.

With event driven programs you are always waiting until the next "thing" happens. So in your case (if I've understood your application correctly) when you start the program it should simply tell the first button to flash "N" times. If you write that as event then the application will return to the waiting state once the code has completed.

Then in the button click event handler - you can subscribe all the buttons to the same event - you can check that the correct button has been pressed and then tell the next button to flash. If the wrong button was pressed then display a suitable message.

So in pseudo code you have:

public class Form
{
    Initialise()
    {
        this.Loaded += FormLoaded;
    }

    private void FormLoaded(object sender, EventArgs e)
    {
        // pick a button
        pickedButton.Flash();
    }

    private void Button_Click(object sender, EventArgs e)
    {
        if (sender == pickedButton)
        {
            pickedButton = pickButton();
        }
        else
        {
            message = "Sorry wrong button, try again";
        }

        pickedButton.Flash();
    }
}

public class Button
{
    public void Flash()
    {
        // loop N times turning button on/off
    }
}
ChrisF
  • 134,786
  • 31
  • 255
  • 325
  • 1
    That doesn't make sense, redpress is a bool that defines whether the button has been clicked or not, I already have an event to set the bool to true when the button is pressed. I need code to make the program wait for the event... – aelsheikh Apr 11 '11 at 22:43
  • @Zizo47 - sorry I misunderstood - put the code you need in the handler where I've indicated with the comment. – ChrisF Apr 11 '11 at 22:45
  • 1
    This still doesn't change a thing, I need to the program to stop and wait for me to click the button, I have no problems with the button itself. – aelsheikh Apr 11 '11 at 22:51
  • @Zizo47 - what do you mean by "stop". If you put the code **inside** the event handler it won't get executed until the button is pressed. – ChrisF Apr 11 '11 at 22:55
  • Let me explain a bit more, this is a simon says game, its waiting flashes the button the user has to press, then "waits" for the user to press it. I want to make it wait within the constraints of that code, so It wont continue so long as the button is pressed. – aelsheikh Apr 11 '11 at 22:58
  • @Zizo47 - I don't fully understand the problem - you want the button to flash "N" times and then stop, and the next button only flash when the user clicks on the first one? In that case all you "main" code needs to do is tell the first button to flash. The program will then wait until it gets further input - in this case the button press. If it's the right one you can then tell the next button to flash. – ChrisF Apr 11 '11 at 23:02
  • Don't worry, I've done a bit of research and apparently what I'm asking for is pretty damn hard. I'll just change the whole code around, thanks for your time anyway. – aelsheikh Apr 11 '11 at 23:04
4

Windows Forms Controls have a Click event you can subscribe to in the form constructor:

myButton.Click += myButton_EventHandler;

You can then put whatever logic you want to happen in the handler and this will execute when the button has been clicked:

private void myButton_EventHandler(object sender, EventArgs e)
{
    Redpress = false;
}

You should avoid blocking (in any way, spinning sleeping etc) the Main thread in your forms applications as this will lock up the interface, there are many methods to avoid this including Timers, Threads, Delegates and BackgroundWorkers to name a few.

EDIT: To include your update

For this you could use a ManualResetEvent.

private readonly ManualResetEvent mre = new ManualResetEvent(false);

private void myButton_EventHandler(object sender, EventArgs e)
{
    mre.Set();
}

Your Form code can wait by calling:

mre.WaitOne();

This will make the executing code wait until the event has fired. Hope that helps.

NOTE: Please don't be mistaken though, unless you have some special case (I can't think of one off the top of my head at this time of night!) you should put the code straight in the event handler, rather than blocking a thread until the event has fired.

trickdev
  • 627
  • 1
  • 7
  • 14
  • All you done there is set redpress to false on with an event, I need the program to wait for "that" event... – aelsheikh Apr 11 '11 at 22:47
0

If you need the program to wait for that event then don't write the waitForTheButton code in your main access/Page load.

Instead write your code inside the event. So you don't have to make an active wait. Events are for that.

eg: If you have something like this

static void Main()
{
    while (notPressed) { }
    DoThis();
    DoThat();
}

Then you could be changing it to:

static void Main
{
    myButton.OnClick += myButton_EventHandler;
}

private void myButton_EventHandler(object sender, EventArgs e)
{
    DoThis();
    DoThat();
}                                     

If you really want to work in a procedural paradigm even when you are using a OOP language, you should use a Semaphore or something like that. But that doesn't seem to be what you actually need, It's more like something you want.

apacay
  • 1,702
  • 5
  • 19
  • 41
0

Not sure why you want to stick there which I believe is the real problem. I guess you are in a code where in some cases you want to execute another code upon user action, then resume the remaining code in the main block.

When I deal with such cases, I use a Queue Controller class of my own. The class actually does AddAction(Action), PlayNext() and HasActions()

So at that point of yours I add the code after your loop to an action in my class and do AddAction.

I also do AddAction(Action, position) at the button event and then while HasActions() PlayNext()

This way I don't block the interface and make sure button code will run between my 2 pieces of code.