1

While creating a sample Winforms application to demonstrate multithreading, I wrote the following code on the button click.

private void button1_Click(object sender, EventArgs e)
    {
        label1.Text = "Processing File. Please wait...";
        Thread.Sleep(2500);            
    }

Ideally, the label text should be updated and then the thread should sleep, that is application becomes unresponsive. But what's really happening is, as soon as I click on the button, the application becomes unresponsive without updating the label value, and it gets updated only after the sleep interval has passed.

Am I missing something?

I understand why this is happening. But my question is, the thread should go to sleep only after updating the label text because that statement is above the sleep statement.

Is that something machine specific? Will it produce different results on different machines?

  • `Thread.Sleep` blocks the UI thread which therefore cannot update the display. Consider using an async/await. – Klaus Gütter Nov 11 '20 at 08:03
  • Do you want to understand why this is happening, or you are searching for a way to prevent this from happening? – Theodor Zoulias Nov 11 '20 at 08:05
  • You can use [DoEvents()](https://stackoverflow.com/q/5181777/1997232) before sleep to let label redraw itself. Another option is to use `async/await` and perform delay with `Task.Delay`. – Sinatr Nov 11 '20 at 08:08
  • Does this answer your question? [C# Label Text Not Updating](https://stackoverflow.com/questions/5680659/c-sharp-label-text-not-updating) – Sinatr Nov 11 '20 at 08:10
  • 4
    *"because that statement is above"* - wrong. Event handler run synchronously blocking UI, so despite `Text` property is set in control it will not be able to `Paint` itself until event handler is finished. – Sinatr Nov 11 '20 at 08:11
  • 1
    *"I understand why this is happening."* <== Nope, you don't. And frankly neither do I. ΙΜΗΟ it would be more logical for the `label1` to be repainted instantly after updating its `Text` property, instead of postponing the redraw for after the completion of the `button1_Click` handler. Surely there must be a reason for this surprising behavior, and I hope I knew it. – Theodor Zoulias Nov 11 '20 at 08:43
  • 3
    When you set the Text of the Label, the TextChanged and Paint events are raised right after (before you call `Thread.Sleep()`). But the Label's Text is changed calling [SetWindowText](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowtextw), which actually just sends a `WM_SETTEXT` message. Unfortunately (?), before the message is received, you have already blocked the UI Thread calling Thread.Sleep(), which is executed after, so the message queue cannot process the message until the UI Thread is done *sleeping* . – Jimi Nov 11 '20 at 09:19
  • 2
    If you instead call `label1.Refresh();` right after you set the Text, the Label is repainted, synchronously (because `Refresh()` calls [UpdateWindow](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-updatewindow)), before `Thread.Sleep()` is called. If you call `label1.Invalidate();` instead, you have the same effect as before, since this method just enqueues a `WM_PAINT` message that is processed after the event handler completes, but, at that point, you have already blocked the UI Thread calling `Thread.Sleep()`. – Jimi Nov 11 '20 at 09:35
  • @TheodorZoulias - It's not more logical to update immediately. Redrawing is incredibly slow, so if you are doing many updates to the UI you want it to redraw only once all of the updates are done. Which is how it works. – Enigmativity Nov 12 '20 at 00:11
  • @Enigmativity I am not sure that redrawing multiple UI controls in a batch will be any faster than doing them one at a time on demand, unless the affected controls have overlapping regions. We could test it by updating, say, 20 `Label` controls in a loop, and calling `label.Refresh()` in the loop. Would you expect the UI to become sluggish this way? – Theodor Zoulias Nov 12 '20 at 04:49
  • @TheodorZoulias - No, you said that it would be more logical if it "repainted instantly after updating its Text property". If that were the case and you updated multiple properties you'd have multiple repaints. I'm just arguing that the way it actually does it is more logical - one repaint regardless of the number of updates. – Enigmativity Nov 12 '20 at 05:30
  • @Enigmativity yes, updating instantly would be more logical, or more intuitive if you prefer, from the standpoint of the novice programmer. I am 99% sure that you too were surprised when you observed the actual behavior for the first time in your life. I don't object that there is logic and reasoning behind this behavior. My argument is that the reasoning is not obvious. About updating the `Label` multiple times inside the same event handler, how common is this? It's not a `ListBox`, it's a freaking `Label`! Btw could you explain why the `ListBox` has `BeginUpdate`/`EndUpdate` methods? – Theodor Zoulias Nov 12 '20 at 06:07
  • @TheodorZoulias - Agreed. Not obvious, but logical. – Enigmativity Nov 12 '20 at 09:36

0 Answers0