Thread.Sleep not working as I would expect in C#









up vote
0
down vote

favorite












This code imitates the problem that I am experiencing in my app.



 private void button1_Click(object sender, EventArgs e)

button1.BackColor = Color.Red;
Thread.Sleep(3000);
button1.BackColor = Color.Green;



I would expect this code to;



  • Make button red

  • Wait 3s

  • Make button green

but instead It is waiting 3s and then making button green. I can't just make the button green from the start as this would not work in my bigger app.



Does anyone have any idea what is wrong and also how i could fix it? Thanks in advance.










share|improve this question

















  • 2




    Your GUI thread has no chance to update the UI to use the red color. Try using async programming model and Task.Delay. For now just add a Thread.Sleep(0) before the 3 second sleep. I Think that should work.
    – Creepin
    Nov 11 at 22:22






  • 1




    Possible duplicate of Thread.Sleep() without freezing the UI
    – mjwills
    Nov 11 at 22:26










  • Painting the screen does not happen immediately, it happens as an event in the event queue. Events are only processed after you return from the current event. So the button believes it is red, but it can never paint to the screen because you did not return, and give the "paint" event a chance.
    – Ben
    Nov 11 at 22:26











  • Possible duplicate of How to put delay before doing an operation in WPF
    – Creepin
    Nov 11 at 22:37














up vote
0
down vote

favorite












This code imitates the problem that I am experiencing in my app.



 private void button1_Click(object sender, EventArgs e)

button1.BackColor = Color.Red;
Thread.Sleep(3000);
button1.BackColor = Color.Green;



I would expect this code to;



  • Make button red

  • Wait 3s

  • Make button green

but instead It is waiting 3s and then making button green. I can't just make the button green from the start as this would not work in my bigger app.



Does anyone have any idea what is wrong and also how i could fix it? Thanks in advance.










share|improve this question

















  • 2




    Your GUI thread has no chance to update the UI to use the red color. Try using async programming model and Task.Delay. For now just add a Thread.Sleep(0) before the 3 second sleep. I Think that should work.
    – Creepin
    Nov 11 at 22:22






  • 1




    Possible duplicate of Thread.Sleep() without freezing the UI
    – mjwills
    Nov 11 at 22:26










  • Painting the screen does not happen immediately, it happens as an event in the event queue. Events are only processed after you return from the current event. So the button believes it is red, but it can never paint to the screen because you did not return, and give the "paint" event a chance.
    – Ben
    Nov 11 at 22:26











  • Possible duplicate of How to put delay before doing an operation in WPF
    – Creepin
    Nov 11 at 22:37












up vote
0
down vote

favorite









up vote
0
down vote

favorite











This code imitates the problem that I am experiencing in my app.



 private void button1_Click(object sender, EventArgs e)

button1.BackColor = Color.Red;
Thread.Sleep(3000);
button1.BackColor = Color.Green;



I would expect this code to;



  • Make button red

  • Wait 3s

  • Make button green

but instead It is waiting 3s and then making button green. I can't just make the button green from the start as this would not work in my bigger app.



Does anyone have any idea what is wrong and also how i could fix it? Thanks in advance.










share|improve this question













This code imitates the problem that I am experiencing in my app.



 private void button1_Click(object sender, EventArgs e)

button1.BackColor = Color.Red;
Thread.Sleep(3000);
button1.BackColor = Color.Green;



I would expect this code to;



  • Make button red

  • Wait 3s

  • Make button green

but instead It is waiting 3s and then making button green. I can't just make the button green from the start as this would not work in my bigger app.



Does anyone have any idea what is wrong and also how i could fix it? Thanks in advance.







c# thread-sleep






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 11 at 22:17









shuriken might

41




41







  • 2




    Your GUI thread has no chance to update the UI to use the red color. Try using async programming model and Task.Delay. For now just add a Thread.Sleep(0) before the 3 second sleep. I Think that should work.
    – Creepin
    Nov 11 at 22:22






  • 1




    Possible duplicate of Thread.Sleep() without freezing the UI
    – mjwills
    Nov 11 at 22:26










  • Painting the screen does not happen immediately, it happens as an event in the event queue. Events are only processed after you return from the current event. So the button believes it is red, but it can never paint to the screen because you did not return, and give the "paint" event a chance.
    – Ben
    Nov 11 at 22:26











  • Possible duplicate of How to put delay before doing an operation in WPF
    – Creepin
    Nov 11 at 22:37












  • 2




    Your GUI thread has no chance to update the UI to use the red color. Try using async programming model and Task.Delay. For now just add a Thread.Sleep(0) before the 3 second sleep. I Think that should work.
    – Creepin
    Nov 11 at 22:22






  • 1




    Possible duplicate of Thread.Sleep() without freezing the UI
    – mjwills
    Nov 11 at 22:26










  • Painting the screen does not happen immediately, it happens as an event in the event queue. Events are only processed after you return from the current event. So the button believes it is red, but it can never paint to the screen because you did not return, and give the "paint" event a chance.
    – Ben
    Nov 11 at 22:26











  • Possible duplicate of How to put delay before doing an operation in WPF
    – Creepin
    Nov 11 at 22:37







2




2




Your GUI thread has no chance to update the UI to use the red color. Try using async programming model and Task.Delay. For now just add a Thread.Sleep(0) before the 3 second sleep. I Think that should work.
– Creepin
Nov 11 at 22:22




Your GUI thread has no chance to update the UI to use the red color. Try using async programming model and Task.Delay. For now just add a Thread.Sleep(0) before the 3 second sleep. I Think that should work.
– Creepin
Nov 11 at 22:22




1




1




Possible duplicate of Thread.Sleep() without freezing the UI
– mjwills
Nov 11 at 22:26




Possible duplicate of Thread.Sleep() without freezing the UI
– mjwills
Nov 11 at 22:26












Painting the screen does not happen immediately, it happens as an event in the event queue. Events are only processed after you return from the current event. So the button believes it is red, but it can never paint to the screen because you did not return, and give the "paint" event a chance.
– Ben
Nov 11 at 22:26





Painting the screen does not happen immediately, it happens as an event in the event queue. Events are only processed after you return from the current event. So the button believes it is red, but it can never paint to the screen because you did not return, and give the "paint" event a chance.
– Ben
Nov 11 at 22:26













Possible duplicate of How to put delay before doing an operation in WPF
– Creepin
Nov 11 at 22:37




Possible duplicate of How to put delay before doing an operation in WPF
– Creepin
Nov 11 at 22:37












3 Answers
3






active

oldest

votes

















up vote
3
down vote













No. it's changing to Red but you are blocking your UI thread and thus you don't see the color changed. What if you change the handler to a async one like



private async Task button1_Click(object sender, EventArgs e)

button1.BackColor = Color.Red;
await Task.Delay(3000);
button1.BackColor = Color.Green;






share|improve this answer



























    up vote
    2
    down vote













    The problem is that with Sleep you are blocking the main (rendering) thread. So you set the button red, but because you are blocking the thread, the app can't render it. In fact, I expect that the whole application freeze.

    I am not sure what are you using, but try to look at some timers.



    EDIT or simply use tasks Delayed function calls. Just do not use threads, please.






    share|improve this answer



























      up vote
      0
      down vote













      The technical reason for this, is the UI works on a Message Pump (in the case of WinForms, or similar in regards to WPF). Basically a message pump is a queue of work items to do, and a while loop like the following



      while(GetMessage(&msg, NULL, 0, 0) > 0) 

      TranslateMessage(&msg);
      DispatchMessage(&msg);



      What is happening, is that when you are processing your click



      1. The click goes into the message queue

      2. Gets processed by the message pump

      3. Goes into your click method

      4. Blocks the thread for x amount of seconds, its still in your method and the pump cant process.

      Why?



      Thread.Sleep()




      Suspends the current thread for the specified amount of time.




      In short, no other messages get processed. In your example you sleep the thread before the pump has had time to process your colour change yet (its still stick processing your click).



      When the messages eventually process, it goes through the backlog (your color changes being part of that), then without pause quickly changes it from one to the other.



      The fix is quite simple, you need to allow your pump to process messages while you wait and as the other answers have eluded to, in modern version on .net we can use the async await pattern, and take advantage of the Task.Delay() method.



      When the program process anything that is prefixed with await,



      1. If you are on the UI thread it captures the context

      2. Starts another thread with a continuation,

      3. lets the message pump continue processing.

      4. When the task has finished (and your delay is over), it returns control back to the original context (the thread you called it from).

      Hey presto. Everything is as it should be






      share|improve this answer




















        Your Answer






        StackExchange.ifUsing("editor", function ()
        StackExchange.using("externalEditor", function ()
        StackExchange.using("snippets", function ()
        StackExchange.snippets.init();
        );
        );
        , "code-snippets");

        StackExchange.ready(function()
        var channelOptions =
        tags: "".split(" "),
        id: "1"
        ;
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function()
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled)
        StackExchange.using("snippets", function()
        createEditor();
        );

        else
        createEditor();

        );

        function createEditor()
        StackExchange.prepareEditor(
        heartbeatType: 'answer',
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader:
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        ,
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        );



        );













        draft saved

        draft discarded


















        StackExchange.ready(
        function ()
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53253796%2fthread-sleep-not-working-as-i-would-expect-in-c-sharp%23new-answer', 'question_page');

        );

        Post as a guest















        Required, but never shown

























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes








        up vote
        3
        down vote













        No. it's changing to Red but you are blocking your UI thread and thus you don't see the color changed. What if you change the handler to a async one like



        private async Task button1_Click(object sender, EventArgs e)

        button1.BackColor = Color.Red;
        await Task.Delay(3000);
        button1.BackColor = Color.Green;






        share|improve this answer
























          up vote
          3
          down vote













          No. it's changing to Red but you are blocking your UI thread and thus you don't see the color changed. What if you change the handler to a async one like



          private async Task button1_Click(object sender, EventArgs e)

          button1.BackColor = Color.Red;
          await Task.Delay(3000);
          button1.BackColor = Color.Green;






          share|improve this answer






















            up vote
            3
            down vote










            up vote
            3
            down vote









            No. it's changing to Red but you are blocking your UI thread and thus you don't see the color changed. What if you change the handler to a async one like



            private async Task button1_Click(object sender, EventArgs e)

            button1.BackColor = Color.Red;
            await Task.Delay(3000);
            button1.BackColor = Color.Green;






            share|improve this answer












            No. it's changing to Red but you are blocking your UI thread and thus you don't see the color changed. What if you change the handler to a async one like



            private async Task button1_Click(object sender, EventArgs e)

            button1.BackColor = Color.Red;
            await Task.Delay(3000);
            button1.BackColor = Color.Green;







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 11 at 22:24









            Rahul

            61.8k114381




            61.8k114381






















                up vote
                2
                down vote













                The problem is that with Sleep you are blocking the main (rendering) thread. So you set the button red, but because you are blocking the thread, the app can't render it. In fact, I expect that the whole application freeze.

                I am not sure what are you using, but try to look at some timers.



                EDIT or simply use tasks Delayed function calls. Just do not use threads, please.






                share|improve this answer
























                  up vote
                  2
                  down vote













                  The problem is that with Sleep you are blocking the main (rendering) thread. So you set the button red, but because you are blocking the thread, the app can't render it. In fact, I expect that the whole application freeze.

                  I am not sure what are you using, but try to look at some timers.



                  EDIT or simply use tasks Delayed function calls. Just do not use threads, please.






                  share|improve this answer






















                    up vote
                    2
                    down vote










                    up vote
                    2
                    down vote









                    The problem is that with Sleep you are blocking the main (rendering) thread. So you set the button red, but because you are blocking the thread, the app can't render it. In fact, I expect that the whole application freeze.

                    I am not sure what are you using, but try to look at some timers.



                    EDIT or simply use tasks Delayed function calls. Just do not use threads, please.






                    share|improve this answer












                    The problem is that with Sleep you are blocking the main (rendering) thread. So you set the button red, but because you are blocking the thread, the app can't render it. In fact, I expect that the whole application freeze.

                    I am not sure what are you using, but try to look at some timers.



                    EDIT or simply use tasks Delayed function calls. Just do not use threads, please.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 11 at 22:21









                    Patrik Valkovič

                    428416




                    428416




















                        up vote
                        0
                        down vote













                        The technical reason for this, is the UI works on a Message Pump (in the case of WinForms, or similar in regards to WPF). Basically a message pump is a queue of work items to do, and a while loop like the following



                        while(GetMessage(&msg, NULL, 0, 0) > 0) 

                        TranslateMessage(&msg);
                        DispatchMessage(&msg);



                        What is happening, is that when you are processing your click



                        1. The click goes into the message queue

                        2. Gets processed by the message pump

                        3. Goes into your click method

                        4. Blocks the thread for x amount of seconds, its still in your method and the pump cant process.

                        Why?



                        Thread.Sleep()




                        Suspends the current thread for the specified amount of time.




                        In short, no other messages get processed. In your example you sleep the thread before the pump has had time to process your colour change yet (its still stick processing your click).



                        When the messages eventually process, it goes through the backlog (your color changes being part of that), then without pause quickly changes it from one to the other.



                        The fix is quite simple, you need to allow your pump to process messages while you wait and as the other answers have eluded to, in modern version on .net we can use the async await pattern, and take advantage of the Task.Delay() method.



                        When the program process anything that is prefixed with await,



                        1. If you are on the UI thread it captures the context

                        2. Starts another thread with a continuation,

                        3. lets the message pump continue processing.

                        4. When the task has finished (and your delay is over), it returns control back to the original context (the thread you called it from).

                        Hey presto. Everything is as it should be






                        share|improve this answer
























                          up vote
                          0
                          down vote













                          The technical reason for this, is the UI works on a Message Pump (in the case of WinForms, or similar in regards to WPF). Basically a message pump is a queue of work items to do, and a while loop like the following



                          while(GetMessage(&msg, NULL, 0, 0) > 0) 

                          TranslateMessage(&msg);
                          DispatchMessage(&msg);



                          What is happening, is that when you are processing your click



                          1. The click goes into the message queue

                          2. Gets processed by the message pump

                          3. Goes into your click method

                          4. Blocks the thread for x amount of seconds, its still in your method and the pump cant process.

                          Why?



                          Thread.Sleep()




                          Suspends the current thread for the specified amount of time.




                          In short, no other messages get processed. In your example you sleep the thread before the pump has had time to process your colour change yet (its still stick processing your click).



                          When the messages eventually process, it goes through the backlog (your color changes being part of that), then without pause quickly changes it from one to the other.



                          The fix is quite simple, you need to allow your pump to process messages while you wait and as the other answers have eluded to, in modern version on .net we can use the async await pattern, and take advantage of the Task.Delay() method.



                          When the program process anything that is prefixed with await,



                          1. If you are on the UI thread it captures the context

                          2. Starts another thread with a continuation,

                          3. lets the message pump continue processing.

                          4. When the task has finished (and your delay is over), it returns control back to the original context (the thread you called it from).

                          Hey presto. Everything is as it should be






                          share|improve this answer






















                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            The technical reason for this, is the UI works on a Message Pump (in the case of WinForms, or similar in regards to WPF). Basically a message pump is a queue of work items to do, and a while loop like the following



                            while(GetMessage(&msg, NULL, 0, 0) > 0) 

                            TranslateMessage(&msg);
                            DispatchMessage(&msg);



                            What is happening, is that when you are processing your click



                            1. The click goes into the message queue

                            2. Gets processed by the message pump

                            3. Goes into your click method

                            4. Blocks the thread for x amount of seconds, its still in your method and the pump cant process.

                            Why?



                            Thread.Sleep()




                            Suspends the current thread for the specified amount of time.




                            In short, no other messages get processed. In your example you sleep the thread before the pump has had time to process your colour change yet (its still stick processing your click).



                            When the messages eventually process, it goes through the backlog (your color changes being part of that), then without pause quickly changes it from one to the other.



                            The fix is quite simple, you need to allow your pump to process messages while you wait and as the other answers have eluded to, in modern version on .net we can use the async await pattern, and take advantage of the Task.Delay() method.



                            When the program process anything that is prefixed with await,



                            1. If you are on the UI thread it captures the context

                            2. Starts another thread with a continuation,

                            3. lets the message pump continue processing.

                            4. When the task has finished (and your delay is over), it returns control back to the original context (the thread you called it from).

                            Hey presto. Everything is as it should be






                            share|improve this answer












                            The technical reason for this, is the UI works on a Message Pump (in the case of WinForms, or similar in regards to WPF). Basically a message pump is a queue of work items to do, and a while loop like the following



                            while(GetMessage(&msg, NULL, 0, 0) > 0) 

                            TranslateMessage(&msg);
                            DispatchMessage(&msg);



                            What is happening, is that when you are processing your click



                            1. The click goes into the message queue

                            2. Gets processed by the message pump

                            3. Goes into your click method

                            4. Blocks the thread for x amount of seconds, its still in your method and the pump cant process.

                            Why?



                            Thread.Sleep()




                            Suspends the current thread for the specified amount of time.




                            In short, no other messages get processed. In your example you sleep the thread before the pump has had time to process your colour change yet (its still stick processing your click).



                            When the messages eventually process, it goes through the backlog (your color changes being part of that), then without pause quickly changes it from one to the other.



                            The fix is quite simple, you need to allow your pump to process messages while you wait and as the other answers have eluded to, in modern version on .net we can use the async await pattern, and take advantage of the Task.Delay() method.



                            When the program process anything that is prefixed with await,



                            1. If you are on the UI thread it captures the context

                            2. Starts another thread with a continuation,

                            3. lets the message pump continue processing.

                            4. When the task has finished (and your delay is over), it returns control back to the original context (the thread you called it from).

                            Hey presto. Everything is as it should be







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 12 at 4:31









                            TheGeneral

                            1




                            1



























                                draft saved

                                draft discarded
















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid


                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.

                                To learn more, see our tips on writing great answers.





                                Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                Please pay close attention to the following guidance:


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid


                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.

                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53253796%2fthread-sleep-not-working-as-i-would-expect-in-c-sharp%23new-answer', 'question_page');

                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                這個網誌中的熱門文章

                                How to read a connectionString WITH PROVIDER in .NET Core?

                                In R, how to develop a multiplot heatmap.2 figure showing key labels successfully

                                Museum of Modern and Contemporary Art of Trento and Rovereto