3

I would like to use the following code in C# but I just can't seem to get out of it. I would like to terminate the application if the user presses a key or moves the rodent (aka mouse). Here is my code (no laughing!).

private void frmDots_KeyDown(object sender, KeyEventArgs e) { bgNotClicked = false; Close(); } private void frmDots_Click(object sender, EventArgs e) { bgNotClicked = false; Close(); } while (bgNotClicked) { // Clear the first element in our XY position. This is the reverse of the way I normally create the dots application System.Drawing.Rectangle clearDots = new System.Drawing.Rectangle(Dots.PositionX[iCounter], Dots.PositionY[iCounter], 8, 8); // Create the black color and brush to clear dots Color clearDotsColor = Color.Black; SolidBrush clearDotsBrush = new SolidBrush(clearDotsColor); // Finally clear the dot e.Graphics.FillEllipse(clearDotsBrush, clearDots); GetRandomPosition(iCounter); // Fill the elements to display colors on the displays canvas System.Drawing.Rectangle colorDots = new System.Drawing.Rectangle(Dots.PositionX[iCounter], Dots.PositionY[iCounter], 8, 8); // Create the color and brush to show dots Color colorRandom = GetRandomColor(); SolidBrush colorBrush = new SolidBrush(colorRandom); // Finally show the dot e.Graphics.FillEllipse(colorBrush, colorDots); Thread.Sleep(5); iCounter++; if (iCounter == 399) { iCounter = 0; } } } 
3
  • 6
    I think I'm going to start calling it a "rodent" from now on always Commented May 1, 2009 at 17:55
  • 1
    Oh my god I just realized rodent means mouse. That's awesome. Commented May 1, 2009 at 17:57
  • @Peter: I updated my answer in response to your edit. The problem is that your UI message pump is being blocked, so your handlers never run. Commented May 1, 2009 at 18:08

11 Answers 11

6

Your "busy waiting" strategy is poor design. Instead, you should use event handlers that are fired:

  • On keypress.
  • When the mouse is moved.

In either case, you can respond by terminating the application.

Sign up to request clarification or add additional context in comments.

1 Comment

Thats easier said than done when one is stuck in a continuous loop.
4

Edit:

After seeing your edit, this is definitely your problem. The issue is that your while loop blocks the main UI thread, so it never handles the Windows Messages which trigger your key press/mouse/etc handlers.

You have a couple of options - you can either move some of this onto a separate thread, do what I suggested below, or add a call to Application.DoEvents in your while loop. This would allow your event handlers to run, which would in turn set bgNotClicked = false;. Right now, that's never occurring because your UI is blocked entirely.


Original Post:

If you're doing this loop in your UI thread, you're going to need to rethink the design a bit.

Setting bgNotClicked = false; somewhere in an event handler will work, but only if your event handler is able to run. If you're doing the above code in the UI thread, it will block your UI thread indefinitely, preventing the event handler from firing.

I would recommend reworking this to be based off a timer (so it runs repeatedly on regular intervals), instead of locked into a while loop. This would allow your other UI events to fire between runs, and instead of setting bgNotClicked = false;, your event handler could just set the timer to be not enabled.

3 Comments

Thank you very much! Application.DoEvents(); did the trick. good job.
@Reed Copsey: on your edit -- Hey! That's what I said! About ten minutes after you. Good one.
@Peter: I'd recommend switching to use the timer approach I mentioned towards the end, though - it would be a much cleaner design, and more in line with the standard windows forms event model. DoEvents can have side effects, at times, that are undesirable.
3

Your bgNotClicked variable needs to be set to false by your event handler for key-press.

If the rodent is moved by your mouse, you would need a similar mouse event handler.

1 Comment

What if a rodent gets on your desk when you're not looking and moves your rodent?
1

The break keyword will terminate a loop. In this case, when you hit the case where you want to stop the loop, you would just use break;.

Comments

1

If you're looping like that you need to give the application a moment to process the events that you're hoping will cause the interruption. This is the job of the DoEvents method.

private bool WeAreDone = false; private void DoingIt() { while (true) { Application.DoEvents(); if (WeAreDone) { break; } } } private void InterruptButton_Click(object sender, EventArgs e) { WeAreDone = true; } 

Comments

1

I think using a Timer fits the Windows event-driven model better than the busy wait while loop. You might try something like this:

public partial class Form1 : Form { public Form1() { InitializeComponent(); } private int iCounter = 0; private void Draw() { // .... } private void timer1_Tick(object sender, EventArgs e) { Draw(); iCounter++; if(iCounter == 399) { iCounter = 0; } } private void Form1_Load(object sender, EventArgs e) { timer1.Interval = 5; timer1.Enabled = true; } private void Form1_Click(object sender, EventArgs e) { timer1.Enabled = false; Close(); } private void Form1_KeyDown(object sender, KeyEventArgs e) { timer1.Enabled = false; Close(); } } 

1 Comment

I think that his while loop is inside the paint message handler (based on having e.Graphics in it), so the timer could just call Invalidate(), and let the paint handler deal with the rest.
0

This does not seems to be the correct way. .Net Framework has provided you with the events to handle the KeyPress and MouseMove/Click actions. Why are you not using them?

Comments

0

Try moving the loop into a BackgroundWorker's DoWork event handler. Then your GUI will still be responsive and instead of that nasty variable, you can just call the CancelAsync method to stop the loop.

2 Comments

it looks like his code interfaces directly with the UI. running on a background worker wouldn't help.
Unless he put it in the ProgressChanged event.
0

You can exit the loop using the break statement.

EDIT: OK, I take back the flag thing!

2 Comments

Why on Earth would the flag need to be global?
Reading that answer hurt my feelings. :( Global anything (including singletons and static classes) make me very very sad.
0

Use Environment.Exit(2); (or Environment.Exit(1) it really doesn't make a difference) to exit out of the application.

Comments

-3
Exit While 

...................

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.