Task.Wait不等待异步方法完成

Gho*_*ter 2 .net c# asynchronous

这是代码:

static async Task Main(string[] args)
{
    var t = new Task(async () => await AsyncTest());
    t.Start();
    t.Wait();
    Console.WriteLine("Main finished");
}

private static async Task AsyncTest()
{
    Thread.Sleep(2000);
    await Task.Delay(2000);
    Console.WriteLine("Method finished");
}
Run Code Online (Sandbox Code Playgroud)

我的期望是t.Wait()实际上将等待AsyncTest方法完成,并且输出将是:

Method finished 
Main finished
Run Code Online (Sandbox Code Playgroud)

实际上输出只有Main finished。当您await Task.Delay(2000)在AsyncTest内部点击时,Wait()即完成。如果t.Wait()await t/ await Task.WhenAll(t)/ 替换,也会发生同样的情况Task.WaitAll(t)

解决方案是将方法重写为同步实现,或者直接在AsyncTest()上调用Wait()。但是,问题是为什么它以这种奇怪的方式起作用?

PS这是代码的简化版本。我试图实现延迟的任务执行。实际上,Task对象是由程序的一个部分创建的,然后在某些特定条件之后由另一部分执行。

UPD:重写VAR t = new Task(async () => await AsyncTest())var t = new Task(()=> AsyncTest().Wait())还解决了问题。虽然我仍然不太明白为什么Task无法在委托中使用async / await正常工作。

Ste*_*ary 7

我仍然不太明白为什么Task在委托内部无法通过async / await正常工作。

因为Task构造函数仅用于创建委托任务 -即代表要运行的同步代码的任务。由于代码是同步的,因此您的asynclambda被视为async voidlambda,这意味着Task实例将不会异步等待AsyncTest完成。

更重要的是,Task构造函数应该永远不会被任何代码中使用,任何地点,以任何理由。它实际上有零个有效用例。

一个很好的替代品Task.TaskTask.Run,它确实了解asynclambda。

在我的真实程序中,任务已推迟执行。任务对象在一个位置创建,然后在特定条件由程序的另一部分执行之后再创建。

在这种情况下,请使用异步委托。具体来说,Func<Task>

static async Task Main(string[] args)
{
    Func<Task> func = AsyncTest;

    // Later, when we're ready to run.
    await func();
    Console.WriteLine("Main finished");
}

private static async Task AsyncTest()
{
    Thread.Sleep(2000);
    await Task.Delay(2000);
    Console.WriteLine("Method finished");
}
Run Code Online (Sandbox Code Playgroud)