using System.Collections.Generic;
using System.Threading.Tasks;
public static class Program
public static async Task Main()
await foreach (string s in BlockingIterator().OffloadEnumerationAsync())
Print($"--Received: {s}");
private static IEnumerable<string> BlockingIterator()
for (int i = 1; i <= 10; i++)
Print($"Producing: {i}");
yield return i.ToString();
public static async IAsyncEnumerable<T> OffloadEnumerationAsync<T>(
this IEnumerable<T> source)
ArgumentNullException.ThrowIfNull(source);
IEnumerator<T> enumerator = await Task.Run(
() => source.GetEnumerator()).ConfigureAwait(false);
(T Value, bool HasValue) item = default;
Task<(T, bool)> moveTask = Task.Run(() =>
bool moved = enumerator.MoveNext();
if (moved) return (enumerator.Current, true);
try { yield return item.Value; yieldOK = true; }
if (!yieldOK) try { await moveTask.ConfigureAwait(false); } catch { }
item = await moveTask.ConfigureAwait(false);
if (!item.HasValue) break;
finally { await Task.Run(() => enumerator?.Dispose()).ConfigureAwait(false); }
private static void Print(object value)
Console.WriteLine($@"{DateTime.Now:HH:mm:ss.fff} [{Thread.CurrentThread
.ManagedThreadId}] > {value}");