3

I do this:

clear();
coinRefundComplete.Visible = true;
state = 0;

System.Threading.Thread.Sleep(4000);
clear();

greeting.Visible = true;
rate.Visible = true;
refundTicket.Visible = true;
currentTime.Visible = true;

I expect the coinRefundComplete Text (it is a label) to appear for 4 seconds, then get cleared by a method I defined with clear(), and then some other stuff happens. Instead after I clear my form with the first clear(), my form is blank for 4 seconds, then finishes properly.

Adil
  • 146,340
  • 25
  • 209
  • 204
73est
  • 185
  • 2
  • 9
  • 2
    You're blocking the UI thread. Changes won't be visible and you should never block it. Use a timer if you want to show something for a moment. – Sami Kuhmonen Nov 10 '16 at 06:31
  • 1
    If all this code is inside one method - then form will not be updated until method will be fully executed. – Fabio Nov 10 '16 at 06:31
  • 1
    insert `Application.DoEvents();` before `System.Threading.Thread.Sleep(4000);` - give the UI a chance to *redraw* the label – Dmitry Bychenko Nov 10 '16 at 06:32
  • @Fabio, so are you saying I cannot clear a form multiple times within 1 method? – 73est Nov 10 '16 at 06:33
  • 1
    @DmitryBychenko - `Application.DoEvents()` is bad. Just as bad - or maybe worse - than calling `Thread.Sleep(...)` on the UI thread. – Enigmativity Nov 10 '16 at 06:47

3 Answers3

11

Use async/await approach.
Make your method async - below example for eventhandler of button click

private async void ButtonClick(object sender, EventArgs e)
{
    clear();
    coinRefundComplete.Visible = true;
    state = 0;

    await Task.Delay(4000);
    clear();

    greeting.Visible = true;
    rate.Visible = true;
    refundTicket.Visible = true;
    currentTime.Visible = true;
}

On line await Task.Delay(4000); UI thread will be release, which will update all changes were made before. After 4 seconds method will continue executing on the UI thread.

Fabio
  • 31,528
  • 4
  • 33
  • 72
  • Thank you, this is what I was looking for. I found multiple questions and answers using this technique, but none of them pointed out that I needed to add "async" to the method definition of the button click. – 73est Nov 10 '16 at 06:36
  • Although this implementation is better in my opinion, as it doesn't freeze the UI, I marked the other answer as correct because it offered a solution using the same idea as my original question (albeit not as good of an overall solution). – 73est Nov 10 '16 at 06:45
  • 1
    @73est - The other solution is a bad idea. It isn't guaranteed to work. You should never ever just sleep the UI thread. This answer is far better. – Enigmativity Nov 10 '16 at 06:48
  • I understand that, and I used this solution in my implementation. But as it stands, the other solution answers my question as to how I would in theory use Thread.Sleep() in this scenario – 73est Nov 10 '16 at 07:38
0

Although putting the GUI thread to sleep is never desirable but allowing the GUI thread to refresh the control state before going to Sleep will show you the changes you want. Call Control.Update or Control.Refresh after making it visible and before going to sleep so that the GUI thread is able to show changes before it goes to sleep.

clear();
coinRefundComplete.Visible = true;
label1.Update();
state = 0;    
System.Threading.Thread.Sleep(4000);
clear();

You should be carefull while using Thread.Sleep, In your case it is GUI thread and GUI will be irresponsive for the time you sleep. Knowing the reason why you want to block thread could bring some other better suggestion.

Edit

You can use other thread for adding delay without blocking the GUI thread. If you can use framework 4.5 then you can use async / await construct or read this article Using async/await without .NET Framework 4.5 .

private async void testAsyncAwaitDely_Click(object sender, EventArgs e)
{
     clear();
     coinRefundComplete.Visible = true;
     state = 0;
     await Task.Delay(4000);
     clear();
     //Your code
}
Adil
  • 146,340
  • 25
  • 209
  • 204
-3

Update [22-Apr-2018]: I've not deleted this answer so that you don't go the wrong path even though my answer is indeed a possible solution to OP's question (specially when it costs me some negative reputation as well). You should read below posts to really convince yourself as to why Application.DoEvents isn't a great solution to this problem:


Your UI is not refreshing because you are doing your entire processing on UI thread so UI thread is not getting any chance to refresh the UI elements. You need to call the Application.DoEvents() function at any place where you seek UI to be refreshed and loaded with latest changes. Here is your modified code. I've added one line of code before calling sleep on the current UI thread:

        clear();
        coinRefundComplete.Visible = true;
        state = 0;

        //new line of code
        System.Windows.Forms.Application.DoEvents();

        System.Threading.Thread.Sleep(4000);
        clear();

        greeting.Visible = true;
        rate.Visible = true;
        refundTicket.Visible = true;
        currentTime.Visible = true;
RBT
  • 24,161
  • 21
  • 159
  • 240
  • 1
    Calling `Application.DoEvents()` is just bad. Very bad. It can cause all sorts of re-entrancy errors. It is only available because of backward compatibility with VB6. Avoid it at all costs. – Enigmativity Nov 10 '16 at 06:49