-2
labelStatus.Content = "Sending email... ";
labelStatus.Foreground = Brushes.Aqua;
Thread.Sleep(3000);
labelStatus.Foreground = Brushes.Pink;

Why the color Aqua didn't show in the result? It is just shows nothing when the code starts running and after 3 seconds the text appears in Pink directly.

thatguy
  • 21,059
  • 6
  • 30
  • 40
Kyung Lee
  • 925
  • 1
  • 10
  • 21

4 Answers4

2

Using Thread.sleep(3000) will freeze the main thread. Instead, assign another thread to do other stuff in the background or use async.

2

You called Thread.Sleep(); method immediately after setting foreground to Brushes.Aqua, so the thread was freezed and it cannot refresh the control. Then when it finally unfreezed after 3000 milliseconds, you changed foreground again to Brushes.Pink.

It should have render the foreground of the label to Aqua first after unfreezed and then to Pink. But it is too soon for people to notice.

You could force thread to refresh the views before you called Thread.Sleep(); method. An example is the WPF-version of DoEvents() method from this answer. Or maybe you can try BackgroundWorker or a async method but I didn't test so not sure it is can work well.

2

Thread.Sleep(3000); will freeze the GUI thread. This operation happens faster than the GUI can change the color, so you won't see it even though the code is executing correctly. The following code should solve your problem:

BackgroundWorker worker = new BackgroundWorker();
labelStatus.Content = "Sending email...";
labelStatus.Foreground = Brushes.Aqua;
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();

...

private void worker_DoWork(object sender, DoWorkEventArgs e)
{
    //Add logic here
    Thread.Sleep(3000);
}

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    labelStatus.Foreground = Brushes.Pink;
}

Note: I'm assuming that you have other logic (eg. sending the email) that needs to occur in place of Thread.Sleep(3000);. It's very rare that you actually need to force the application to hang.

Wellerman
  • 846
  • 4
  • 14
2

Using Thread.Sleep is a blocking call, which means the UI thread is suspended, so the UI freezes.

Suspends the current thread for the specified amount of time.

I guess you call your method in a button event handler. What you can do is add the async keyword to the event handler method and replace the call to Sleep with Task.Delay and await it.

private async void OnClick(object sender, RoutedEventArgs e)
{
   labelStatus.Content = "Sending email... ";
   labelStatus.Foreground = Brushes.Aqua;
   await Task.Delay(3000);
   labelStatus.Foreground = Brushes.Pink;
}

This way, the UI thread will not be blocked and the Foreground will be set to Pink, after the delay expires.

However, this is not the right approach either. Sending an email or doing other kinds of operations can vary in time, as there are differences in bandwidth, latency or just less resources. You cannot and should not depend on a fixed timespan to wait and hope that an operation is completed. Instead use e.g. the async/await pattern to make your operation run asnychronously and return when it is really completed, like the delay above. This will keep your UI responsive, regardless of whether the operation completed earlier or later.

thatguy
  • 21,059
  • 6
  • 30
  • 40