I have two asynchronous sequences that I want to "zip" in pairs, and for this purpose I used the Zip
operator from the System.Linq.Async package. This operator behaves in an undesirable way though, at least for my case. Instead of enumerating the two sequences concurrently, it enumerates them sequentially, with the result being that the latency is added up. Each of my sequences emits an element every one second on average, and I expected that the combined sequence would also emit zipped pairs every one second, but in reality I get one pair every 2 seconds. Below is a minimal example that demonstrates this behavior:
static async IAsyncEnumerable<int> First()
{
for (int i = 1; i <= 5; i++) { await Task.Delay(1000); yield return i; }
}
static async IAsyncEnumerable<int> Second()
{
for (int i = 1; i <= 5; i++) { await Task.Delay(1000); yield return i; }
}
var stopwatch = Stopwatch.StartNew();
await foreach (var pair in First().Zip(Second()))
Console.WriteLine(pair);
Console.WriteLine($"Duration: {stopwatch.ElapsedMilliseconds:#,0} msec");
Output:
(1, 1)
(2, 2)
(3, 3)
(4, 4)
(5, 5)
Duration: 10,155 msec
Is there any way that I can Zip
these two sequences in a way that the program completes in 5 seconds instead of 10? I am interested about a custom operator, or about a combination of operators from the official packages, that has the desirable behavior.