Task的OnCompleted回调在哪里?

问题描述 投票:3回答:2

我希望能够做到这一点:

class MyClass
{
    IRepo repo;
    public MyClass(IMyRepo repo) { this.repo = repo; }

    long ID { get; set; }
    string Prop1 { get; set; }
    string Prop2 { get; set; }

    public async Task LoadAsync()
    {
        await Task.WhenAll(
            repo.GetProp1ByIDAsync(ID).OnComplete(x => Prop1 = x),
            repo.GetProp2ByIDAsync(ID).OnComplete(x => Prop2 = x)
        );
    }
}

当然,我似乎找不到任何具有OnComplete扩展名Task的标准库。我是否真的需要创建自己的库,或者是否已经有此扩展方法的库?我看到有ContinueWith,但是那不能给我解开的结果,我仍然必须await.Result它...所以那不会阻塞线程吗?保持第二个repo通话直到完成?如果不能解决问题,那么为什么我仍将结果包装好,将未包装的结果退还给我会更干净吗?还是我错过了什么?

c# callback async-await task
2个回答
2
投票

我似乎找不到任何具有此Task的OnComplete扩展名的标准库。我是否真的需要创建自己的库,或者是否已经有此扩展方法的库?我看到这里有ContinueWith,但这并不能给我带来解包的结果,我仍然必须等待它或结果。因此,那不会阻塞线程吗?

ContinueWith是您要寻找的方法; Result不会阻止该任务,因为在调用回调时该任务已经完成。

但是,ContinueWith是危险的低级API。您应该改用await

public async Task LoadAsync()
{
    await Task.WhenAll(
        LoadProp1Async(),
        LoadProp2Async()
    );
}

private async Task LoadProp1Async()
{
  Prop1 = await repo.GetProp1ByIDAsync(ID);
}

private async Task LoadProp2Async()
{
  Prop2 = await repo.GetProp2ByIDAsync(ID);
}

2
投票

首先您应该选择await Task.WhenAll(...),而不是.WaitAll

ContinueWith是您需要在完成时启动另一个任务的条件。在传递给.Result的解包结果上调用ContinueWith将立即返回,因为任务已经完成,如果您等待它,则同样如此。

在第一个任务上调用.ContinueWith对第二个任务无效,并且当您稍后使用await Task.WhenAll(...)等待它们时,它们将并发执行。

link示例检出此ReadFileAsync

© www.soinside.com 2019 - 2024. All rights reserved.