问题
Background: I am writing an application that iterates through a list of servers and obtains various details about each machine. During the iteration, I need to update various controls on the form (to display a summary of the obtained information). Because it is iterating through a list, I have called a Thread.Sleep() to allow the user time to read through the information before the next machine is interrogated. Below is my code:
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);
This works fine regarding updating the controls on the form, but during the Thread.Sleep() the UI locks up. Surely if the Thread.Sleep() is called on a separate task, the UI thread has remained unblocked?
回答1:
Task.Delay should suit your needs.
Change
Task.Factory.StartNew(() =>
to
Task.Factory.StartNew(async () =>
and change
Thread.Sleep
to
await Task.Delay
回答2:
If you pass the UiScheduler as TaskScheduler then that task is running on the UI thread. So yes, the UI thread is completely blocked when you call Thread.Sleep.
If you want to delay use await Task.Delay(10000) instead to delay asynchronously.
That will make the task returned from Task.Factory.StartNew a Task<Task> because it wasn't build with async-await in mind unlike Task.Run. To fix that use Task.Unwrap on the returned Task:
Task<Task> TestTask = Task.Factory.StartNew(async () =>
{
// ...
await Task.Delay(10000);
// ...
}, CancellationToken.None, TaskCreationOptions.None, UiScheduler);
Task actualTask = TestTask.Unwrap();
回答3:
use Task.Delay instead of Thread.Sleep
checkout This link for more details
来源:https://stackoverflow.com/questions/31960351/keeping-ui-responsive-during-a-thread-sleep