首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Task.Wait不等待异步方法的完成

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

Stack Overflow用户
提问于 2019-06-04 09:51:20
回答 4查看 3.4K关注 0票数 3

以下是代码:

代码语言:javascript
复制
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方法的完成,输出将是:

代码语言:javascript
复制
Method finished 
Main finished

实际上,输出只有Main finished。等一下()就在你点击await Task.Delay(2000)在AsyncTest里面的时候就已经完成了。如果将t.Wait()替换为await t / await Task.WhenAll(t) / Task.WaitAll(t),也会发生同样的情况。

解决方案是重写方法以同步实现或直接在AsyncTest()上调用Wait()。然而,问题是,为什么它的工作方式如此奇怪?

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

UPD:将var t = new Task(async () => await AsyncTest())重写为var t = new Task(()=> AsyncTest().Wait())也解决了这个问题。尽管我仍然不太明白为什么任务不能在异步/等待内部委托中正确工作。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-06-04 13:50:13

我仍然不太明白为什么任务不能在异步/等待内部委托中正确工作。

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

更重要的是,构造函数永远不应该在任何代码中,任何地方,出于任何原因被使用。。它几乎没有有效的用例。

Task.Task的一个很好的替代品是Task.Run,它确实理解async lambdas。

在我真正的程序中,任务已经推迟了执行。任务对象在一个地方创建,然后在程序的另一部分执行特定条件之后创建。

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

代码语言:javascript
复制
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");
}
票数 8
EN

Stack Overflow用户

发布于 2019-06-04 10:29:39

@JonSkeet的报价

异步方法只返回void,这意味着没有简单的方法等待它完成。(您几乎总是应该避免使用异步空方法。它们实际上只有为了订阅事件才能使用。)

因此,看看这行代码:

代码语言:javascript
复制
var t = new Task(async () => await AsyncTest());

查看Task构造函数的签名:

代码语言:javascript
复制
    public Task(Action action);
    public Task(Action action, CancellationToken cancellationToken);       
    public Task(Action action, TaskCreationOptions creationOptions);
    public Task(Action<object> action, object state);
    public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions);
    public Task(Action<object> action, object state, CancellationToken cancellationToken);
    public Task(Action<object> action, object state, TaskCreationOptions creationOptions);
    public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions);

它们都是Actions,如您所知,Action具有void返回类型。

代码语言:javascript
复制
static async Task Main(string[] args)
{
    // best way to do it
    await AsyncTest();


    Console.WriteLine("Main finished");
}

private static async Task AsyncTest()
{
    // Don't use thread sleep, await task delay is fine
    // Thread.Sleep(2000);

    await Task.Delay(2000);
    Console.WriteLine("Method finished");
}
票数 1
EN

Stack Overflow用户

发布于 2019-06-04 10:30:03

看看这个

代码语言:javascript
复制
public static async Task Main(string[] args)
{
    var t = Task.Factory.StartNew(async () => await AsyncTest());
    //t.Start();
    t.Result.Wait();    
    t.Wait();
    Console.WriteLine("Main finished");
}

private static async Task AsyncTest()
{
    //Thread.Sleep(2000);
    await Task.Delay(2000);
    Console.WriteLine("Method finished");
}

而这个链接

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56441486

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档