public async Task LimitingConcurrency()
{
#region Cancellation AsAbove
var tokenSource = new CancellationTokenSource();
tokenSource.CancelAfter(TimeSpan.FromSeconds(1));
var token = tokenSource.Token;
#endregion
#region Task Tracking AsAbove
var runningTasks = new ConcurrentDictionary<Task, Task>();
#endregion
var semaphore = new SemaphoreSlim(2);
var pumpTask = Task.Run(async () =>
{
while (!token.IsCancellationRequested)
{
#region Output
"Pumping...".Output();
#endregion
await semaphore.WaitAsync().ConfigureAwait(false);
#region HandleMessage AsAbove
var runningTask = HandleMessage();
runningTasks.TryAdd(runningTask, runningTask);
#endregion
runningTask.ContinueWith(t =>
{
#region Output
"... done".Output();
#endregion
semaphore.Release();
#region Housekeeping AsAbove
Task taskToBeRemoved;
runningTasks.TryRemove(t, out taskToBeRemoved);
#endregion
}, TaskContinuationOptions.ExecuteSynchronously)
.Ignore();
}
});
#region Awaiting completion AsAbove
await pumpTask.ConfigureAwait(false);
#region Output
"Pump finished".Output();
#endregion
await Task.WhenAll(runningTasks.Values).ConfigureAwait(false);
#region Output
"All receives finished".Output();
#endregion
tokenSource.Dispose();
semaphore.Dispose();
#endregion
}