不能在承诺风格的任务上调用 Start.异常来了 [英] Start may not be called on a promise-style task. exception is coming
问题描述
我正在创建一个简单的 wpf 桌面应用程序.UI 在 .cs 文件中只有一个按钮和代码.
I am creating a simple wpf desktop application. UI have just a button and code in .cs file like.
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
:
But surprisingly line Task.Delay(5000).Start();
is throwing an InvalidOperationException
:
不能在 Promise 风格的任务上调用 Start.
Start may not be called on a promise-style task.
有人能帮忙解释一下为什么会这样吗?
Can any one help why it is like this?
推荐答案
您收到该错误是因为 Task
类在将任务交给您之前已经启动了该任务.您应该只在通过调用其构造函数创建的任务上调用 Start
,并且您甚至不应该这样做,除非您有令人信服的理由在创建任务时不启动它;如果您希望它立即启动,您应该使用 Task.Run
或 Task.Factory.StartNew
来创建和启动新的 Task
.
You are getting that error because the Task
class already started the task before giving it to you. You should only ever call Start
on a task that you create by calling its constructor, and you shouldn't even do that unless you have a compelling reason to not start the task when you create it; if you want it started right away you should use Task.Run
or Task.Factory.StartNew
to both create and start a new Task
.
所以,现在我们知道摆脱那个讨厌的Start
.您将运行您的代码并发现消息框立即显示,而不是 5 秒后,这是怎么回事?
So, now we know to just get rid of that pesky Start
. You'll run your code and find that the message box is shown right away, not 5 seconds later, what's up with that?
好吧,Task.Delay
只是给你一个将在 5 秒内完成的任务.它不会停止线程的执行 5 秒.您想要做的是在该任务完成后执行一些代码.这就是 ContinueWith
的用途.它允许您在完成给定任务后运行一些代码:
Well, Task.Delay
just gives you a task that will be completed in 5 seconds. It doesn't stop execution of the thread for 5 seconds. What you want to do is have some code that's executed after that task finishes. That's what ContinueWith
is for. It lets you run some code after a given task is done:
public void FunctionA()
{
Task.Delay(5000)
.ContinueWith(t =>
{
MessageBox.Show("Waiting Complete");
});
}
这将按预期运行.
我们还可以利用 C# 5.0 的 await
关键字更轻松地添加延续:
We could also leverage C# 5.0's await
keyword to add continuations more easily:
public async Task FunctionA()
{
await Task.Delay(5000);
MessageBox.Show("Waiting Complete");
}
虽然对这里发生的事情的完整解释超出了这个问题的范围,但最终结果是一种行为与前一种方法非常相似的方法;它会在您调用该方法 5 秒后显示一个消息框,但在这两种情况下,该方法本身都会[几乎] 立即返回.也就是说,await
非常强大,它允许我们编写看似简单直接的方法,但直接使用 ContinueWith
编写会更加困难和混乱.它还极大地简化了错误处理,去掉了大量样板代码.
While a full explanation of what's going on here is beyond the scope of this question, the end result is a method that behaves very similar to the previous method; it will show a message box 5 seconds after you call the method, but the method itself will return [almost] right away in both cases. That said, await
is very powerful, and allows us to write methods that seem simple and straightforward, but that would be much harder and messier to write using ContinueWith
directly. It also greatly simplifies dealing with error handling, taking out a lot of boilerplate code.
这篇关于不能在承诺风格的任务上调用 Start.异常来了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!