private static async Task ExecuteJob(AsyncJob asyncJob) { Debug.Assert(asyncJob != null); // observe cancellation token if (_AbortTokenSource.IsCancellationRequested) { return; } try { // if semaphore is empty, wait until it is released await _WorkerSemaphore.WaitAsync().ConfigureAwait(false); // signal JobStarted event OnJobStarted(asyncJob); // execute job without context dependence await asyncJob.Execute().ConfigureAwait(false); // signal JobFinished event OnJobFinished(asyncJob); } finally { // release semaphore regardless of any job errors _WorkerSemaphore.Release(); } }