using System.Collections.Generic;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
public static class Program
public static async Task Main()
var sequence_A = Range("A{0}", 1, 5);
var sequence_B = Range("B{0}", 1, 3);
var sequence_C = Range("C{0}", 1, 7);
var merged = Interleave(sequence_A, sequence_B, sequence_C);
await foreach (var item in merged) Console.WriteLine(item);
public static IAsyncEnumerable<T> Interleave<T>(params IAsyncEnumerable<T>[] sources) =>
Interleave(default, sources);
public static async IAsyncEnumerable<T> Interleave<T>([EnumeratorCancellation] CancellationToken token, IAsyncEnumerable<T>[] sources)
var enumerators = new List<IAsyncEnumerator<T>>(sources.Length);
for(var i = 0; i < sources.Length; i++)
enumerators.Add(sources[i].GetAsyncEnumerator(token));
if(await enumerators[j].MoveNextAsync())
yield return enumerators[j].Current;
if(j >= enumerators.Count)
await enumerators[j].DisposeAsync();
} while (enumerators.Count > 0);
for(var i = 0; i < enumerators.Count; i++)
await enumerators[i].DisposeAsync();
static async IAsyncEnumerable<string> Range(string text, int start, int count) {
for (int i = 0; i < count; i++)
yield return string.Format(text, start + i);