c# - Start 可能不会在 promise 风格的任务上被调用。异常(exception)来了

标签 c# c#-4.0 .net-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");
}

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

Start may not be called on a promise-style task.

谁能帮忙解释为什么会这样?

最佳答案

您收到该错误是因为 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");
    });
}

这将按预期运行。

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

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

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

关于c# - Start 可能不会在 promise 风格的任务上被调用。异常(exception)来了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14230372/

相关文章:

c# - 插入windows键盘缓冲区

c# - 如何在 C# Winform 中更改文本框中某些子字符串的字体颜色?

c# - Process.Start 启动进程两次而不是一次

c# - 在 C# 中迭代​​ JSON 对象

c# - Validation.ErrorTemplate 确实在绑定(bind)到对象属性时触发

c# - 如何在 C# 正则表达式中获取捕获组的名称?

regex - 用单个 Regex.Replace() 替换多个字符串 Replace()

c# - 如何配置 IronPython.StdLib 2.7.3

visual-studio-2010 - 从 .net 4.0 转换为 .net 3.5 时出现错误.. 无法加载文件或程序集 'System.Drawing,Version 4.0.0.0, Culture=natural...' 错误

c# - 压缩弱引用字典