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

Chr*_*ght 4 c# multithreading task

背景:我正在编写一个应用程序,它遍历服务器列表并获取有关每台机器的各种详细信息.在迭代期间,我需要更新表单上的各种控件(以显示所获取信息的摘要).因为它正在遍历列表,所以我调用了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);
Run Code Online (Sandbox Code Playgroud)

这在更新窗体上的控件时工作正常,但在Thread.Sleep()期间,UI会锁定.当然,如果在单独的任务上调用Thread.Sleep(),UI线程仍然未被阻塞?

Dan*_*ode 5

Task.Delay应该适合您的需求.

更改

Task.Factory.StartNew(() =>
Run Code Online (Sandbox Code Playgroud)

Task.Factory.StartNew(async () =>
Run Code Online (Sandbox Code Playgroud)

并改变

Thread.Sleep
Run Code Online (Sandbox Code Playgroud)

await Task.Delay
Run Code Online (Sandbox Code Playgroud)


i3a*_*non 5

如果您传递UiScheduleras,TaskScheduler则该任务正在UI线程上运行.所以是的,当您调用时,UI线程被完全阻止Thread.Sleep.

如果你想延迟使用await Task.Delay(10000)而不是异步延迟.

这将使任务从Task.Factory.StartNewa 返回,Task<Task>因为它不是用async-await构建的,不像Task.Run.要Task.Unwrap在返回的Task上修复该用法:

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

Task actualTask = TestTask.Unwrap();
Run Code Online (Sandbox Code Playgroud)