【问题标题】:C# how to combine 2 Task<IEnumerable<T>> via Union and return taskC#如何通过Union组合2个Task<IEnumerable<T>>并返回任务
【发布时间】:2018-10-02 21:07:31
【问题描述】:

现在我有 2 个Task&lt;IEnumerable&lt;T&gt;&gt;,分别称为 TaskA 和 TaskB。我需要将 TaskC 传递给异步方法。在那个方法中,它处于等待状态,并且对生成的 IEnumerable 进行了操作,我无法更改该方法。

我想要做的是以某种方式说“当等待 TaskC 时,然后等待 TaskA,并将这些结果与等待的 TaskB 的结果联合”。

如果 IEnumerables 没有包含在 Tasks 中,我当然会这样做:

var ResultC = ResultA.Union(ResultB);

如何在仍然懒惰地评估 TaskA 和 TaskB 的同时完成此任务?

【问题讨论】:

    标签: c# linq asynchronous async-await


    【解决方案1】:

    如果IEnumerables 没有包裹在Tasks 中,我当然会这样做:

    var ResultC = ResultA.Union(ResultB);
    

    如何在仍然懒惰地评估 TaskA 和 TaskB 的同时完成此任务?

    请记住,await TaskA异步等待任务完成并提取其结果值的操作。所以你可以简单地说:

    Task<IEnumerable<T>> resultA = whatever;
    Task<IEnumerable<T>> resultB = whatever;
    Func<Task<IEnumerable<T>>> getTaskC = 
      async () => (await resultA).Union(await resultB); 
    Task<IEnumerable<T>> resultC = getTaskC();
    

    现在你手头有一个任务,它代表“异步等待 A 和 B,然后取它们的并集”的工作流程。

    【讨论】:

    • 考虑到这个答案的代码,注意不要替换 lambda:whatever 中的whateverasync () =&gt; (await whateverA).Union(await whateverB)。这会导致两个任务的执行序列化。
    【解决方案2】:

    WhenAll 等待两者,然后取结果的并集。

    public async Task<IEnumerable<T>> GetUnion<T>(Task<IEnumerable<T>> a, Task<IEnumerable<T>> b)
    {
        await Task.WhenAll(a,b);
        return a.Result.Union(b.Result);
    }
    

    然后这样称呼它:

    var results = await GetUnion(TaskA,TaskB);
    

    这是DotNetFiddle 上的一个工作示例

    【讨论】:

    • 你能说为什么必须使用WhenAll吗?为什么不直接写return (await a).Union(await b);
    • @MAW74656:如果你想要任务而不是结果,那就用GetUnion(TaskA, TaskB)吧!
    • @MAW74656:根据您的问题,我怀疑您对await 的含义有不正确的心理模型。这意味着“如果等待的任务已完成,则提取其值并继续;如果尚未完成,则将此方法的其余部分注册为任务的继续并将控制权交还给我的调用者”。这就是“评估等待表达式”的含义。
    • @MAW74656:请记住,当您调用异步方法时,它会执行以下四种操作之一:(1) 进入无限循环并且永不返回,(2) 引发异常,(3) 等待不完整的任务和挂起,返回一个不完整的任务,(4)返回一个完成的任务。这是异步方法唯一可以做的四件事!
    • @MAW74656:我明白你在说什么。是的,使用 Task 构造函数会生成一个“冷”任务,直到您调用 Start 才会启动。但是async 方法创建的任务在 C# 中总是“热”的。那么在您的示例中,任务 A 和 B 是否已经开始?一般来说,在 C# 中,阻止一个任务的启动并不容易。我们设计了异步工作流,假设如果你有一个任务,你希望它执行。
    猜你喜欢
    • 1970-01-01
    • 2013-04-26
    • 2016-09-23
    • 2015-06-28
    • 1970-01-01
    • 2017-11-18
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多