0

I want the text of a Label to change along with its colour after a Button has been pressed.
The first part is meant to change the Text and also the the ForeColor to Color.Orange, then wait 1 second before changing the Text property again and setting ForeColor to Color.LightGreen.

My issue is that it doesn't do it in that order, it just skips the first part and changes to the 2nd part (the text changes to "finished!" and the colour to light green).

Here is my code:

private void button1_Click(object sender, EventArgs e)
{
    label6.Text = "Working..";
    label6.ForeColor = Color.Orange;

    System.Threading.Thread.Sleep(1000);
    label6.Text = "Finsihed!";
    label6.ForeColor = Color.LightGreen;
}
Jimi
  • 29,621
  • 8
  • 43
  • 61
  • 1
    Don't use `Sleep` in UI thread. Mainly because it will block the form from user interraction, what you experience is just another effect of using it. There are other approaches to [delay something](https://stackoverflow.com/q/9112305/1997232): using `Timer` and `async/await` (the best among other forms of multithreading) are most recommended. – Sinatr Jul 28 '21 at 09:32

2 Answers2

1

you need to tell your label to update before you do the sleep

private void button1_Click(object sender, EventArgs e)
{
    label6.Text = "Working..";
    label6.ForeColor = Color.Orange;
    label6.Update(); // tell the label to update now

    System.Threading.Thread.Sleep(1000);
    label6.Text = "Finished!";
    label6.ForeColor = Color.LightGreen;
    label6.Update(); // tell the label to update now
}

But there is another way to do this. When you use async and use Task.Delay() instead of Thread.Sleep() with your click method there is no need to call the Update() statement.
And this also keeps your form responsive.

here is an example of how you can do this in your situation.

private async void button1_Click(object sender, EventArgs e)
{
    label6.Text = "Working..";
    label6.ForeColor = Color.Orange;

    await System.Threading.Tasks.Task.Delay(1000);
    label6.Text = "Finished!";
    label6.ForeColor = Color.LightGreen;
}

So, which is better, the Update() or the async ?
Well that depends

When you just use the Update with Thread.Sleep() than your form will update, as you want. But it will also not respond to anything until your Thread.Sleep() has finished.
This can be a bad thing, but it can also be a good thing.
That depends on your situation. Maybe you don't want the users to be able to do anything at all until the Thread.Sleep() is finished. But it also means the user cannot drag the form to some other position. That might be annoying for the user.

When you use async and Task.Delay() then your form will also update, as you want. But it will also respond to other actions, like dragging, resizing, clicks, etc...
If you want this, then this is the way to go.
If you dont want this, then either use the Update() again, or make sure the user cannot click on anything he is not supposed to.
The latter is a nice solution, because the user will still be able to drag the form where he wants it whyle the operation is running, but still cannot do anything wrong.
This means that before you start the operation, disable all controls he should not be able to click on, then start the operation and when it finishes enable all these controls again.
Agreed, this is more work, but it looks much nicer for the user.

So in my opinion using the async and Task.Delay() is the better solution.

GuidoG
  • 11,359
  • 6
  • 44
  • 79
0

As you are in the primary thread of the application, no updates to the screen will occur whilst you are in the Sleep section (you have put the whole program to sleep) To Get the change to appear, do an Application.DoEvents(); before the sleep - this allows the screen updates to occur

Andrew B.
  • 1
  • 2
  • 1
    never never never never use Application.DoEvents() !!!!!!!! That can cause the order of events to change, which can bring you in much more troubles. If you need to do Application.DoEvents() then there is something fundamental wrong in your application. – GuidoG Jul 28 '21 at 09:57
  • please read [this](https://blog.codinghorror.com/is-doevents-evil/) and also [this](https://stackoverflow.com/questions/5181777/use-of-application-doevents) – GuidoG Jul 28 '21 at 10:10
  • @GuidoG: while your admonition to not use `Application.DoEvents()` is accurate, I find it ironic that you then would post an answer suggesting the use of `Control.Update()`, which is every bit as bad a choice. If you need `Update()`, then there is something fundamental wrong in your application, just as if `DoEvents()` is needed. – Peter Duniho Jul 28 '21 at 17:43
  • @PeterDuniho Well that is just not true. Though they both have influence on the message queue, Control.Update() has no side effects like DoEvents does. It is safe to use. I agree that using async is better, but saying they are just as bad is actually wrong. – GuidoG Jul 29 '21 at 05:29
  • @GuidoG: you can disagree all you like. – Peter Duniho Jul 29 '21 at 06:23
  • @PeterDuniho I am not going into a discussion about this, that never brings any good. It is not a matter of agreeing or not, it is a matter of facts. – GuidoG Jul 29 '21 at 06:45
  • @GuidoG: a person who was not _"going into a discussion about this"_ would not have posted another comment on the topic. The _fact_ is that no properly written program ever needs to call the `Update()` method. Period. You can disagree all you like; that is your prerogative. But there is no _factual_ basis for that disagreement. – Peter Duniho Jul 29 '21 at 06:53