// this is a sync-over-async; don't do it // [Benchmark(OperationsPerInvoke = CC_LOAD * CC_LOAD)] public async Task <int> AsyncSemaphore_ConcurrentLoad() { var tasks = Enumerable.Range(0, CC_LOAD).Select(async _ => { int success = 0; for (int t = 0; t < CC_LOAD; t++) { _asyncSemaphore.Wait(); try { success++; await Task.Yield(); } finally { _asyncSemaphore.Release(); } await Task.Yield(); } return(success); }).ToArray(); await Task.WhenAll(tasks).ConfigureAwait(false); int total = tasks.Sum(x => x.Result); return(total.AssertIs(CC_LOAD * CC_LOAD)); }
internal static TResult Implementation <TResult>( Func <CancellationToken, TResult> action, Context context, Action <Context> onBulkheadRejected, SemaphoreSlim maxParallelizationSemaphore, SemaphoreSlim maxQueuedActionsSemaphore, CancellationToken cancellationToken) { if (!maxQueuedActionsSemaphore.Wait(TimeSpan.Zero, cancellationToken)) { onBulkheadRejected(context); throw new BulkheadRejectedException(); } try { maxParallelizationSemaphore.Wait(cancellationToken); try { return(action(cancellationToken)); } finally { maxParallelizationSemaphore.Release(); } } finally { maxQueuedActionsSemaphore.Release(); } }
internal static async Task <TResult> ImplementationAsync <TResult>( Func <CancellationToken, Task <TResult> > action, Context context, Func <Context, Task> onBulkheadRejectedAsync, SemaphoreSlim maxParallelizationSemaphore, SemaphoreSlim maxQueuedActionsSemaphore, CancellationToken cancellationToken, bool continueOnCapturedContext) { if (!await maxQueuedActionsSemaphore.WaitAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(continueOnCapturedContext)) { await onBulkheadRejectedAsync(context).ConfigureAwait(continueOnCapturedContext); throw new BulkheadRejectedException(); } try { await maxParallelizationSemaphore.WaitAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext); try { return(await action(cancellationToken).ConfigureAwait(continueOnCapturedContext)); } finally { maxParallelizationSemaphore.Release(); } } finally { maxQueuedActionsSemaphore.Release(); } }