首页 > 解决方案 > 如果我使用 new Task(action) -> .Start() 而不是 Task.Run() 创建任务,为什么在调用任何异步方法时任务会停止执行?

问题描述

我发现如果使用以下方式构造一个新任务: var task = new Task(async action); task.Start();,任何异步方法( , 等)的任何调用都会await Task.Delay()忽略await new WebClient().DownloadStringAsync()运算await符并立即返回主线程。

如果我使用Task.Run(async action)方式运行相同的操作,那么相同的代码将按预期工作。

示例代码:

class Program
{
    static async Task Main()
    {
        // way1 - it's working
        var goodTask = Task.Run(async () => await ProblemMethod("goodTask"));
        await goodTask;
        Console.WriteLine($"{DateTime.Now:HH:mm:ss} :: {nameof(goodTask)} is finished.");

        // way2 - it fails without any exceptions on line with GetRequestStreamAsync
        var poorTask = new Task(async () => await ProblemMethod("poorTask"));
        poorTask.Start();
        await poorTask;
        Console.WriteLine($"{DateTime.Now:HH:mm:ss} :: {nameof(poorTask)} is finished.");

        Console.ReadLine();
    }

    static async Task ProblemMethod(string taskName)
    {
        Console.WriteLine($"{taskName} :: {DateTime.Now:HH:mm:ss} :: It's a first line.");
        await Task.Delay(2000);
        Console.WriteLine($"{taskName} :: {DateTime.Now:HH:mm:ss} :: It's a last line.");
    }
}

控制台输出:

goodTask :: 18:52:50 :: It's a first line.
goodTask :: 18:52:52 :: It's a last line.
18:52:52 :: goodTask is finished.
poorTask :: 18:52:52 :: It's a first line.
18:52:52 :: poorTask is finished.
poorTask :: 18:52:54 :: It's a last line.

为什么会有如此奇怪的行为?而且,是的,我知道首选和推荐的方法是通过 Task.Run 或 Task.Factory.StartNew 立即运行任务,但是如果我不想立即运行我的任务该怎么办?

标签: c#async-awaittap

解决方案


答案在这里讨论。本质上,Task构造需要 aAction<>而不是 a Func<>,因此异步委托并没有真正被这样对待。


推荐阅读