可能不会在promise样式的任务上调用Start.例外即将来临

D J*_*D J 104 c# .net-4.0 c#-4.0

我正在创建一个简单的wpf桌面应用程序.UI只有一个按钮和.cs文件中的代码.

private void Button_Click_2(object sender, RoutedEventArgs e)
{
    FunctionA();
}

public void FunctionA()
{
    Task.Delay(5000).Start();
    MessageBox.Show("Waiting Complete");
}
Run Code Online (Sandbox Code Playgroud)

但令人惊讶的Task.Delay(5000).Start();是,线路投掷了InvalidOperationException:

可能不会在promise样式的任务上调用Start.

任何人都能帮助为什么会这样吗?

Ser*_*rvy 163

您收到该错误,因为Task该类已经在将该任务提供给您之前已经启动了该任务.你应该只调用Start你通过调用它的构造函数创建的任务,你甚至不应该这样做,除非你有一个令人信服的理由在创建它时不启动任务; 如果你想立即开始,你应该使用Task.RunTask.Factory.StartNew创建和开始新的Task.

所以,现在我们知道要摆脱那种麻烦Start.您将运行您的代码并发现消息框立即显示,而不是5秒后,该怎么办?

好吧,Task.Delay只给你一个将在5秒内完成的任务.它不会停止执行该线程5秒钟.你想要做的是拥有一些在该任务完成后执行的代码.这ContinueWith是为了什么.它允许您在完成给定任务后运行一些代码:

public void FunctionA()
{
    Task.Delay(5000)
    .ContinueWith(t => 
    {
        MessageBox.Show("Waiting Complete");
    });
}
Run Code Online (Sandbox Code Playgroud)

这将按预期运行.

我们还可以利用C#5.0的await关键字更轻松地添加延续:

public async Task FunctionA()
{
    await Task.Delay(5000);
    MessageBox.Show("Waiting Complete");
}
Run Code Online (Sandbox Code Playgroud)

虽然对此处发生的事情的完整解释超出了本问题的范围,但最终结果是一种行为与前一种方法非常相似; 它会在你调用方法后5秒显示一个消息框,但在这两种情况下,方法本身将立即返回[几乎].也就是说,await它非常强大,并且允许我们编写看似简单明了的方法,但ContinueWith直接使用它会变得更加困难和混乱.它还大大简化了错误处理的处理,取出了大量的样板代码.