在Thread.Sleep()期间保持UI响应

本文关键字:UI 响应 Thread Sleep | 更新日期: 2023-09-27 18:07:30

背景:我正在编写一个应用程序,它遍历服务器列表并获取每台机器的各种详细信息。在迭代过程中,我需要更新表单上的各种控件(以显示获取信息的摘要)。因为它正在遍历一个列表,所以我调用了Thread.Sleep(),让用户在查询下一台机器之前有时间阅读信息。下面是我的代码:

Task TestTask = Task.Factory.StartNew(() =>
            {
                foreach (String IpAddress in ServersToCheck)
                {
                    if (IpAddress != String.Empty)
                    {
                        ServerBeingCheckedLabel.Text = IpAddress;
                        if (PingServer(IpAddress) == true)
                        {
                            PingChar_Label.ForeColor = Color.Green;
                            PingChar_Label.Text = "a";
                            CheckPermissionsAreValid(IpAddress);
                        }
                        else
                        {
                            PingChar_Label.ForeColor = Color.Red;
                            PingChar_Label.Text = "r";
                            PermChar_Label.ForeColor = Color.Red;
                            PermChar_Label.Text = "r";
                        }
                    }
                }
                Thread.Sleep(10000);
                this.BackColor = FormBackGroundColor;
                TestButton.Enabled = true;
                RunTimer.Enabled = true;
            }, CancellationToken.None, TaskCreationOptions.None, UiScheduler);

对于更新表单上的控件,这工作得很好,但在Thread.Sleep()期间,UI被锁定。当然,如果在一个单独的任务上调用thread . sleep (), UI线程仍然保持未阻塞?

在Thread.Sleep()期间保持UI响应

任务。延迟应该适合你的需要。

改变
Task.Factory.StartNew(() =>

Task.Factory.StartNew(async () =>

和改变

Thread.Sleep

await Task.Delay

如果您将UiScheduler传递为TaskScheduler,则该任务正在UI线程上运行。所以,当你调用Thread.Sleep时,UI线程被完全阻塞了。

如果您想延迟,使用await Task.Delay(10000)代替异步延迟。

这将使从Task.Factory.StartNew返回的任务成为Task<Task>,因为它不像Task.Run那样构建async-await。要解决这个问题,请在返回的Task上使用Task.Unwrap:

Task<Task> TestTask = Task.Factory.StartNew(async () =>
{
    // ...
    await Task.Delay(10000);
    // ...
}, CancellationToken.None, TaskCreationOptions.None, UiScheduler);
Task actualTask = TestTask.Unwrap();

使用Task.Delay代替Thread.Sleep查看此链接了解更多详情