Reputation: 851
A basic C# Problem.
I have two disabled textboxes on my form, and one button. The button is currently like so:
private void start_Click(object sender, EventArgs e)
{
this.two();
this.hold();
this.one()
}
As you can see it calls three other methods that are like so:
The problem I am encountering is that program seems to skip the first call to two. And just hold the program for a second and change one textbox to black.
Thanks for any help!
Upvotes: 2
Views: 3483
Reputation: 71573
What you are probably experiencing is that you are running this code on the application's main thread, which is also responsible for responding to Windows GUI messages (like the command to repaint itself after you have changed the textboxes' colors). The program currently does not process this message until after this event handler has completely executed, at which time only one textbox is black.
Application.DoEvents(), as mentioned, will solve the problem by interrupting this handler and allowing the program to process the queued messages from the GUI before proceeding. Another way to do this would be to run this code in a BackgroundWorker, which would use a separate processing thread to tell the GUI thread to recolor the textboxes, while not blocking the GUI thread with the Sleep() command. Generally, using a multithreaded approach is better, as Application.DoEvents() can cause unexpected consequences by forcing the invocation of other event handlers while the current one hasn't finished (for instance, a call to another event handler that throws an exception will throw out through the Application.DoEvents call of the one you've interrupted, which didn't actually have a problem).
Upvotes: 3
Reputation: 48985
As other mentioned, it's because your UI thread began to sleep before having started to refresh the display.
Never call Thread.Sleep
on the UI thread. It'll "block" your program and angers your users. If you have some job to do which requires Thread.Sleep
, create a new thread but don't do it in the UI thread.
Upvotes: 3
Reputation: 54887
Since you’re executing your Thread.Sleep
on the UI thread, your form does not get a chance to update itself and repaint with the new colors.
You can introduce an Application.DoEvents
call before your hold
; however, as others have pointed out, this would result in your UI thread remaining frozen (and unresponsive to user activity) for the one-second delay.
The best way to introduce a delay in your logic is to use a Timer
. Here is some sample code which executes two
after a one-second delay.
Timer timer = new Timer { Interval = 1000 };
timer.Tick += (sender, e) =>
{
this.Invoke(new Action(two));
timer.Stop();
timer.Dispose();
};
timer.Start();
Upvotes: 1
Reputation: 38526
Try this:
private void start_Click(object sender, EventArgs e)
{
this.two();
Application.DoEvents();
this.hold();
this.one();
}
Calling DoEvents();
allows the window to repaint in the middle of the click handler, rather than waiting until completion.
Edit: Please read the comments on this answer... You'll see that it's "bad practice" to perform blocking operations like this.
Upvotes: 2
Reputation: 292465
It doesn't skip the call to two
, but since you're blocking the UI thread with your call to Thread.Sleep
, the UI never has a chance to refresh to show the effects of two
.
You could do something like this:
private void start_Click(object sender, EventArgs e)
{
this.two()
Task.Factory.StartNew(() => this.hold())
.ContinueWith(_ => this.one(), TaskScheduler.FromCurrentSynchronizationContext());
}
It will execute hold
in a new thread (thus not freezing the UI) then, when hold
is complete, it will execute two
on the UI thread.
Upvotes: 2