public virtual IFetchedJob FetchNextJob(string[] queues, CancellationToken cancellationToken) { if (queues == null) { throw new ArgumentNullException(nameof(queues)); } if (queues.Length == 0) { throw new ArgumentException("Queue array must be non-empty.", nameof(queues)); } MongoFetchedJob fetchedJob = null; var tryAllQueues = true; while (fetchedJob == null) { cancellationToken.ThrowIfCancellationRequested(); if (tryAllQueues) { fetchedJob = TryAllQueues(queues, cancellationToken); } if (fetchedJob != null) { // make sure to try to decrement semaphore if we succeed in getting a job from the queue _semaphore.WaitNonBlock(fetchedJob.Queue); return(fetchedJob); } if (_semaphore.WaitAny(queues, cancellationToken, _storageOptions.QueuePollInterval, out var queue, out var timedOut)) { fetchedJob = TryGetEnqueuedJob(queue, cancellationToken); } // at this point only try all queues if semaphore timed out tryAllQueues = timedOut; } return(fetchedJob); }