private async Task Execute() { var cancelToken = _cancellationTokenSource.Token; while (!cancelToken.IsCancellationRequested) { Activity activity = default; try { var activeCount = 0; lock (_activeTasks) { activeCount = _activeTasks.Count; } if (activeCount >= MaxConcurrentItems) { await Task.Delay(Options.IdleTime); continue; } activity = WorkflowActivity.StartConsume(Queue); var item = await QueueProvider.DequeueWork(Queue, cancelToken); if (item == null) { activity?.Dispose(); if (!QueueProvider.IsDequeueBlocking) { await Task.Delay(Options.IdleTime, cancelToken); } continue; } activity?.EnrichWithDequeuedItem(item); var hasTask = false; lock (_activeTasks) { hasTask = _activeTasks.ContainsKey(item); } if (hasTask) { _secondPasses.Add(item); if (!EnableSecondPasses) { await QueueProvider.QueueWork(item, Queue); } activity?.Dispose(); continue; } _secondPasses.TryRemove(item); var waitHandle = new ManualResetEvent(false); lock (_activeTasks) { _activeTasks.Add(item, waitHandle); } var task = ExecuteItem(item, waitHandle, activity); } catch (OperationCanceledException) { } catch (Exception ex) { Logger.LogError(ex, ex.Message); activity?.RecordException(ex); } finally { activity?.Dispose(); } } List <EventWaitHandle> toComplete; lock (_activeTasks) { toComplete = _activeTasks.Values.ToList(); } foreach (var handle in toComplete) { handle.WaitOne(); } }