using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Threading.Tasks;
static readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
static async Task Main(string[] args)
Console.WriteLine("Completely out of order ...");
var outOfOrder = Observable.Range(1, 4)
.Select(x => LongProcessAsync(x).ToObservable())
.Do(x => Console.WriteLine($"{x} concatenated"));
await outOfOrder.RunAsync(CancellationToken.None);
Console.WriteLine("Kinda in order ...");
var kindaInOrder = Observable.Range(1, 4)
.Select(x => LongProcessAsync(x).ToObservable())
.Do(x => Console.WriteLine($"{x} concatenated"));
await kindaInOrder.RunAsync(CancellationToken.None);
Console.WriteLine("Completely in order ...");
var completelyInOrder = Observable.Range(1, 4)
.Select(x => OrderedLongProcessAsync(x).ToObservable())
.Do(x => Console.WriteLine($"{x} concatenated"));
await completelyInOrder.RunAsync(CancellationToken.None);
static async Task<int> LongProcessAsync(int n)
Console.WriteLine($"Job {n} started");
await Task.Delay(TimeSpan.FromSeconds(4 - n));
Console.WriteLine($"Job {n} done");
static async Task<int> OrderedLongProcessAsync(int n)
await semaphore.WaitAsync();
return await LongProcessAsync(n);