.NET Fiddle

CSharp · Console

/Program.cs

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static async Task Main()
    {
        var stopwatch = Stopwatch.StartNew();
        await foreach (var pair in Zip(First(), Second()))
            Console.WriteLine(pair);
        Console.WriteLine($"Duration: {stopwatch.ElapsedMilliseconds:#,0} msec");

        static async IAsyncEnumerable<int> First()
        {
            for (int i = 1; i <= 5; i++) { await Task.Delay(100); yield return i; }
        }
        static async IAsyncEnumerable<int> Second()
        {
            for (int i = 1; i <= 5; i++) { await Task.Delay(100); yield return i; }
        }
    }
	
	public static async IAsyncEnumerable<(TFirst, TSecond)> Zip<TFirst, TSecond>(IAsyncEnumerable<TFirst> first, IAsyncEnumerable<TSecond> second)
	{
		await using var e1 = first.GetAsyncEnumerator();	
		await using var e2 = second.GetAsyncEnumerator();
		
		while (true)
		{
			var t1 = e1.MoveNextAsync().AsTask();
			var t2 = e2.MoveNextAsync().AsTask();
			await Task.WhenAll(t1, t2);
			
			if (!t1.Result || !t2.Result)
				yield break;
			
			yield return (e1.Current, e2.Current);
		}
	}
}
;