背景:我正在编写一个应用程序,它遍历服务器列表并获取有关每台计算机的各种详细信息。在迭代期间,我需要更新表单上的各种控件(以显示所获取信息的摘要)。因为它正在遍历列表,所以我调用了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线程仍然被解除阻塞?
答案 0 :(得分:5)
Task.Delay应该符合您的需求。
更改
Task.Factory.StartNew(() =>
到
Task.Factory.StartNew(async () =>
并更改
Thread.Sleep
到
await Task.Delay
答案 1 :(得分:5)
如果您将UiScheduler
作为TaskScheduler
传递,那么该任务正在UI线程上运行。所以,是的,当您致电Thread.Sleep
时,UI线程被完全阻止。
如果您想延迟使用await Task.Delay(10000)
而不是异步延迟。
这将使Task.Factory.StartNew
Task<Task>
返回任务,因为与Task.Run
不同,它不是以async-await构建的。要在返回的任务上修复使用Task.Unwrap
:
Task<Task> TestTask = Task.Factory.StartNew(async () =>
{
// ...
await Task.Delay(10000);
// ...
}, CancellationToken.None, TaskCreationOptions.None, UiScheduler);
Task actualTask = TestTask.Unwrap();
答案 2 :(得分:1)
使用Task.Delay
代替Thread.Sleep
结帐This链接了解更多详情