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

Why Task stops executing on call any async method if I create it with new Task(action) -> .Start() instead of 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 立即 运行 任务,但是如果我不想 [=30] 我该怎么办=] 我的任务立即执行?

讨论了答案here。本质上,Task 构造采用 Action<> 而不是 Func<>,因此异步委托并没有真正被如此对待。