不能在承诺风格的任务上调用 Start.异常来了 [英] Start may not be called on a promise-style task. exception is coming

查看:31
本文介绍了不能在承诺风格的任务上调用 Start.异常来了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个简单的 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.RunTask.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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆