开始可能不会被承诺风格的任务调用。 exception即将到来

我正在创build一个简单的wpf桌面应用程序。 用户界面只有一个button和代码在.cs文件中。

private void Button_Click_2(object sender, RoutedEventArgs e) { FunctionA(); } public void FunctionA() { Task.Delay(5000).Start(); MessageBox.Show("Waiting Complete"); } 

但令人惊讶的行Task.Delay(5000).Start(); 抛出一个InvalidOperationException

开始可能不会被承诺风格的任务调用。

任何人都可以帮助为什么它是这样的?

你得到这个错误是因为Task类在给你之前已经开始了任务。 你只能通过调用它的构造函数来调用Start来创build一个任务,除非你有一个令人信服的理由,当你创build它时不能启动任务,否则你不应该这么做。 如果你想立即开始,你应该使用Task.RunTask.Factory.StartNew来创build和启动一个新的Task

所以,现在我们知道摆脱那个讨厌的Start 。 你会运行你的代码,并发现消息框立即显示,不是5秒钟后,这是怎么回事?

那么, Task.Delay只是给你一个任务,将在5秒内完成。 它不会停止执行线程5秒钟。 你想要做的是在任务结束后执行一些代码。 这就是ContinueWith目的。 它可以让你在一个给定的任务完成后运行一些代码:

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

这将会像预期的那样行事。

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

 public async Task FunctionA() { await Task.Delay(5000); MessageBox.Show("Waiting Complete"); } 

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

尝试这个。

 private void Button_Click_2(object sender, RoutedEventArgs e) { FunctionA(); } public async void FunctionA() { await Task.Delay(5000); MessageBox.Show("Waiting Complete"); } 

Servy说,任务已经开始了,所以你只需要等待(.Wait()):

 private void Button_Click_2(object sender, RoutedEventArgs e) { FunctionA(); } public void FunctionA() { Task.Delay(5000).Wait(); MessageBox.Show("Waiting Complete"); }