如何异步查询两个 IAsyncEnumerables

Xav*_*rAM 4 c# async-await iasyncenumerable

我有两种方法连接到两个不同的Foos源,它们返回两个IAsyncEnumerable<Foo>. Foo在能够处理它们之前,我需要从两个来源获取所有s。

问题:我想同时(异步)查询两个源,即。Source1在开始枚举之前不等待完成枚举Source2。根据我的理解,这就是SequentialSourcesQuery下面的方法示例中发生的情况,对吗?

对于常规任务,我只会开始第一个任务,然后是第二个,然后调用await Task.WhenAll. 但我对如何处理有点困惑IAsyncEnumerable

public class FoosAsync
{
    public async IAsyncEnumerable<Foo> Source1() { }

    public async IAsyncEnumerable<Foo> Source2() { }

    public async Task<List<Foo>> SequentialSourcesQuery()
    {
        List<Foo> foos = new List<Foo>();

        await foreach (Foo foo1 in Source1())
        {
            foos.Add(foo1);
        }

        await foreach (Foo foo2 in Source2())
        { //doesn't start until Source1 completed the enumeration? 
            foos.Add(foo2);
        }

        return foos;
    }
}
Run Code Online (Sandbox Code Playgroud)

The*_*ias 5

您可以利用System.Linq.AsyncSystem.Interactive.Async库(由属于 .NET Foundation的RxTeam所有)。它们包含运营商愿意MergeToListAsync能够轻松解决你的问题。

// Merges elements from all of the specified async-enumerable sequences
// into a single async-enumerable sequence.
public static IAsyncEnumerable<TSource> Merge<TSource>(
    params IAsyncEnumerable<TSource>[] sources);

// Creates a list from an async-enumerable sequence.
public static ValueTask<List<TSource>> ToListAsync<TSource>(
    this IAsyncEnumerable<TSource> source,
    CancellationToken cancellationToken = default);
Run Code Online (Sandbox Code Playgroud)

把所有东西放在一起:

public Task<List<Foo>> SequentialSourcesQuery()
{
    return AsyncEnumerableEx.Merge(Source1(), Source2()).ToListAsync().AsTask();
}
Run Code Online (Sandbox Code Playgroud)

意识到这些库专注于提供丰富的功能集,而不是性能或效率。因此,如果一流的性能对您的用例很重要,niki.kante 的解决方案很可能会胜过上述基于运算符的方法。