Task.Wait不等待异步方法完成 [英] Task.Wait doesn't wait for async method completion

查看:246
本文介绍了Task.Wait不等待异步方法完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是代码:

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");
}

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

My expectation is that t.Wait() will actually wait for AsyncTest method completion and output will be:

Method finished 
Main finished

实际上输出仅主要完成。当您在AsyncTest中点击 await Task.Delay(2000)时,Wait()即完成。如果将 t.Wait()替换为 await t / await Task,也会发生同样的情况。 WhenAll(t) / Task.WaitAll(t)

In reality output has only Main finished. Wait() is completed right at the moment when you hit await Task.Delay(2000) inside AsyncTest. The same happens if you replace t.Wait() with await t / await Task.WhenAll(t) / Task.WaitAll(t).

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

The solution is to rewrite method to synchronous implementation or call Wait() directly on AsyncTest(). However, the question is why does it work in such strange way?

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

P.S. It's a simplified version of code. I was trying to achieve deferred task execution. In reality Task object is created by one part of program and then later is executed by another part after some specific condition.

UPD:重写var t =新任务(async()=>等待AsyncTest()) var t =新任务(()=> AsyncTest()。Wait())也可以解决此问题。尽管我仍然不太明白为什么Task无法在委托中使用async / await正常工作。

UPD: Rewriting var t = new Task(async () => await AsyncTest()) to var t = new Task(()=> AsyncTest().Wait()) also fixes the problem. Though I still don't quite understand why Task doesn't work correctly with async/await inside delegate.

推荐答案


我还是不太明白为什么Task无法在委托中使用async / await正常工作。

I still don't quite understand why Task doesn't work correctly with async/await inside delegate.

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

Because the Task constructor is only used for creating Delegate Tasks - i.e., tasks that represent synchronous code to be run. Since the code is synchronous, your async lambda is being treated as an async void lambda, which means the Task instance won't asynchronously wait for AsyncTest to complete.

更重要的是, Task 构造函数永远不应出于任何原因在任何地方的任何代码中使用。它的字面上是零个有效用例。

More to the point, the Task constructor should never, ever be used in any code, anywhere, for any reason. It has literally zero valid use cases.

Task.Task 的很好替代是 Task.Run 确实能够理解异步 lambda。

A good replacement for Task.Task is Task.Run, which does understand async lambdas.

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

In my real program Task has deferred execution. Task object is created in one place, and then later after specific condition executed by another part of program.

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

In that case, use an asynchronous delegate. Specifically, 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");
}

这篇关于Task.Wait不等待异步方法完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆