【问题标题】:Why does this program just hang?为什么这个程序只是挂起?
【发布时间】:2013-08-27 01:38:19
【问题描述】:

我有以下程序:

static void Main(string[] args) { RunTest(); }

    private static void RunTest() {
        DoIOWorkFiveTimesAsync().Wait();
    }

    private static async Task DoIOWorkFiveTimesAsync() {
        for (int i = 0; i < 5; ++i) {
            Console.WriteLine("Before: " + i);
            await DoIOWorkAsync();
            Console.WriteLine("After: " + i);
        }
    }

    private static Task DoIOWorkAsync() {
        Console.WriteLine("Doing work...");
        return new Task(() => Thread.Sleep(1500));
    }

我希望看到:

  Before: 1
  Doing work...
  After: 1
  Before: 2
  Doing work...
  After: 2
  Before: 3
  Doing work...
  After: 3
  Before: 4
  Doing work...
  After: 4
  Before: 5
  Doing work...
  After: 5

但相反,它会:

Before: 1
Doing work...

而且永远不会有任何进展。我已经尝试并尝试理解 C#5 中的 async/await 功能,但总是没有效果。再一次,我无法解释。

【问题讨论】:

  • 如果你有一个SynchronizationContext 结果会很明显,阻塞等待会阻止继续被安排,但由于你没有设置一个,这不应该发生......
  • 您应该使用Task.Delay 创建一个将在 X 毫秒内完成的任务,而不是您正在执行的操作。您的方法在等待期间阻塞了一个线程。

标签: c# .net asynchronous async-await


【解决方案1】:

问题是您使用的是return new Task(() =&gt; Thread.Sleep(1500)); 而不是Task.Run

new Task 不会真正启动任务,这将导致await 永远不会触发。

请尝试:

private static Task DoIOWorkAsync() {
    Console.WriteLine("Doing work...");
    return Task.Run(() => Thread.Sleep(1500));
}

或者,更好的是:

private static async Task DoIOWorkAsync() {
    Console.WriteLine("Doing work...");
    await Task.Delay(1500);
}

【讨论】:

    【解决方案2】:

    很简单,你返回了一个Task,但你没有启动它。

    如果您将代码更改如下:

    private static Task DoIOWorkAsync()
    {
        Console.WriteLine("Doing work...");
        Task work = new Task(() => Thread.Sleep(1500));
        work.Start();
        return work;
    }
    

    它按你的预期工作。

    【讨论】:

    • 嗯...我认为 await 会启动任务。谢谢。
    • 如果您明确创建任务,我认为如果您将函数定义为 async 就像您对 DoIOWorkFiveTimesAsync 所做的那样,它会将该函数包装在 Task 中并自动启动它(编译器生成必要的代码)。
    • @Motig 一般来说,使用Task.Run 返回一个已经开始的任务是个好主意,而不是依赖任何东西来为你启动任务。在早期预览中,await 会启动任务,但它不再启动,并假定它正在运行。 new Task 几乎总是一个坏主意...
    • 好的,我同意你的观点,但是我仍然看不到 async/await 对任何人的实际作用。如果我从中删除 async/await,上面的所有代码都将完全相同。
    • @Motig 是的,在您的示例中,使用它没有意义。但是,在您有 SynchronizationContext 的情况下(例如在 Form 或 WPF 应用程序上),主线程可能会在您等待时执行其他工作。 async/await 的意义在于,await 之前的代码与await 之后的代码发生在相同的SynchronizationContext(认为“线程”)上,而不会在您等待项目时阻塞SynchronizationContext完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    • 2010-09-18
    相关资源
    最近更新 更多