Why does Thread.Sleep() freeze the Form?

前端 未结 6 876
忘掉有多难
忘掉有多难 2021-01-22 03:38

I try to experiment with Thread.Sleep(). I created basic Windows Forms application with one button.

    private void button1_Click(object sender, Ev         


        
相关标签:
6条回答
  • 2021-01-22 03:53

    For that you better use a Timer but if you want your current code to work you need to add Application.DoEvents(); after you update the button.Label += "."

    0 讨论(0)
  • 2021-01-22 03:58

    EDIT: After programming for a few more years, I now know how terrible of a practice this is. DO NOT DO ANYTHING I SUGGESTED BELOW. It's all crap. A more proper solution would be doing all of your intensive methods async all together. Regardless, don't do what I mention below.

    All The methods above do work however, I do recommend just using an async void.
    Sleep() just pauses the current thread for int amount of milliseconds, and if your whole program runs off of 1 thread, it'll pause the whole program. Don't quote me on this, I do believe that async creates a new thread specifically for that function.

    Below I've included a better sleep function.

    To call the function asleep(milliseconds), replace "milliseconds" with how many milliseconds you wish to sleep for.

    Function Code:

    public async void asleep(int time){
        await Task.Delay(time)
    }
    
    0 讨论(0)
  • 2021-01-22 04:02

    To keep the UI active, you need for the main UI thread to service its message pump. It can only do that when it is not handling UI events. In your case the function

    private void button1_Click(object sender, EventArgs e)
    {
        Thread thread1 = new Thread(DoStuff);
        thread1.Start();
    
        for (int i = 0; i < 100000; i++)
        {
            Thread.Sleep(500);
            button1.Text +=".";
        }
    }
    

    does not return for around 100000*500 milliseconds. While this event handler is executing, the UI thread is busy. It is executing this event handler. As such it is not able to service the message pump. Hence your application's UI freezes.

    0 讨论(0)
  • 2021-01-22 04:04

    If you're new to multithreading, I strongly encourage you to look at the Task Parallel Library (TPL). It simplifies threading, and gives you tools to help guarantee callback (continuation) threads occur on the UI thread.

    The TPL is in the System.Threading.Tasks namespace.

    Update: just seen your comment about .Net v2. TPL was introduced in .NET v3.5 or possibly as late as v4.

    0 讨论(0)
  • 2021-01-22 04:06

    Re-arrange code as following

    private void button1_Click(object sender, EventArgs e)
    {
            Thread thread1 = new Thread(DoStuff);
            thread1.Start();
    }
    
    public void DoStuff()
    {     
            for (int i = 0; i < 100000; i++)
            {
                Thread.Sleep(500);
                //Invoke goes here
            }
    }
    

    Now you run your WORK in a separate thread and release your UI thread for usual work (Drawing related or other work)

    NOTE - Now you will need Invoke methods to change Button text , else you will get warning for "Cross-thread operation not valid"

    More on Invokes - How to update the GUI from another thread in C#?

    0 讨论(0)
  • 2021-01-22 04:10

    Thread.Sleep just sleeps the current thread (i.e. stops it from doing anything, such as redrawing, processing clicks etc), which in your case is the UI thread. If you put the Sleep in DoStuff you wouldn't experience the block as you'd be on a separate thread although you wouldn't be able to update button1. Depending on the version of .NET you're using consider using the Task Parallel Library, something like this:

    private TaskScheduler _uiScheduler;
    public Form1()
    {
        InitializeComponent();
        _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
    }
    
    private void button1_Click(object sender, EventArgs e)
    {
    
        Thread thread1 = new Thread(DoStuff);
        thread1.Start();
    
        // Create a task on a new thread.
        Task.Factory.StartNew(() =>
            {
                for (int i = 0; i < 100000; i++)
                {
                    Thread.Sleep(500);
    
                    // Create a new task on the UI thread to update the button
                    Task.Factory.StartNew(() =>
                        { button1.Text += "."; }, CancellationToken.None, TaskCreationOptions.None, _uiScheduler);
                }
            });
    }
    
    0 讨论(0)
提交回复
热议问题