コード例 #1
0
        public override IFetchedJob FetchNextJob(string[] queueNames, CancellationToken cancellationToken)
        {
            using (var ready = new SemaphoreSlim(0, queueNames.Length))
            {
                var waitNode  = new InMemoryQueueWaitNode(ready);
                var waitAdded = false;

                while (!cancellationToken.IsCancellationRequested)
                {
                    // TODO: Ensure duplicate queue names do not fail everything
                    var entries = _dispatcher.GetOrAddQueues(queueNames);

                    foreach (var entry in entries)
                    {
                        if (entry.Value.Queue.TryDequeue(out var jobId))
                        {
                            _dispatcher.SignalOneQueueWaitNode(entry.Value);
                            return(new InMemoryFetchedJob(_dispatcher, entry.Key, jobId));
                        }
                    }

                    if (!waitAdded && ready.CurrentCount == 0)
                    {
                        foreach (var entry in entries)
                        {
                            _dispatcher.AddQueueWaitNode(entry.Value, waitNode);
                        }

                        waitAdded = true;
                        continue;
                    }

                    ready.Wait(cancellationToken);
                    waitAdded = false;
                }
            }

            cancellationToken.ThrowIfCancellationRequested();
            return(null);
        }
コード例 #2
0
        public override IFetchedJob FetchNextJob([NotNull] 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));
            }

            using (var cancellationEvent = cancellationToken.GetCancellationEvent())
            {
                var entries     = _dispatcher.GetOrAddQueues(queues).ToArray();
                var readyEvents = new WaitHandle[entries.Length + 1];
                var waitAdded   = new bool[entries.Length];

                try
                {
                    for (var i = 0; i < entries.Length; i++)
                    {
                        readyEvents[i] = new AutoResetEvent(false);
                    }

                    readyEvents[entries.Length] = cancellationEvent.WaitHandle;

                    while (!cancellationToken.IsCancellationRequested)
                    {
                        foreach (var entry in entries)
                        {
                            if (entry.Value.Queue.TryDequeue(out var jobId))
                            {
                                _dispatcher.SignalOneQueueWaitNode(entry.Value);
                                return(new InMemoryFetchedJob(_dispatcher, entry.Key, jobId));
                            }
                        }

                        for (var i = 0; i < entries.Length; i++)
                        {
                            if (!waitAdded[i])
                            {
                                _dispatcher.AddQueueWaitNode(entries[i].Value, new InMemoryQueueWaitNode((AutoResetEvent)readyEvents[i]));
                                waitAdded[i] = true;
                            }
                        }

                        var ready = WaitHandle.WaitAny(readyEvents, TimeSpan.FromSeconds(1));
                        if (ready != WaitHandle.WaitTimeout && ready < entries.Length)
                        {
                            waitAdded[ready] = false;
                        }
                    }

                    cancellationToken.ThrowIfCancellationRequested();
                    return(null);
                }
                finally
                {
                    for (var i = 0; i < entries.Length; i++)
                    {
                        readyEvents[i]?.Dispose();
                    }
                }
            }
        }