Beispiel #1
0
        public Task ProduceTasksAsync(int numberOfTasks)
        {
            ManualResetEvent bufferSpaceAvailableWaitHandle =
                new ManualResetEvent(false);

            Queue <Type> taskPayloadTypes =
                new Queue <Type>(mPayloadTypes);

            return(Task.Run(() =>
            {
                Type currentPayloadType;
                IQueuedTaskToken newTaskToken;
                QueuedTask newTask;
                QueuedTaskResult newLastTaskResult;

                EventHandler handleBufferElementRemoved
                    = (s, e) => bufferSpaceAvailableWaitHandle.Set();

                mTaskBuffer.QueuedTaskRetrieved
                    += handleBufferElementRemoved;

                while (taskPayloadTypes.TryDequeue(out currentPayloadType))
                {
                    for (int i = 0; i < numberOfTasks; i++)
                    {
                        newTask = new QueuedTask(Guid.NewGuid())
                        {
                            Payload = Activator.CreateInstance(currentPayloadType),
                            Type = currentPayloadType.FullName
                        };

                        newLastTaskResult = new QueuedTaskResult(newTask)
                        {
                            Status = QueuedTaskStatus.Unprocessed
                        };

                        newTaskToken = new MockQueuedTaskToken(newTask, newLastTaskResult);

                        mProducedTasks.Add(newTaskToken);

                        while (!mTaskBuffer.TryAddNewTask(newTaskToken))
                        {
                            bufferSpaceAvailableWaitHandle.WaitOne();
                            bufferSpaceAvailableWaitHandle.Reset();
                        }
                    }
                }

                mTaskBuffer.CompleteAdding();
                mTaskBuffer.QueuedTaskRetrieved
                    -= handleBufferElementRemoved;
            }));
        }
Beispiel #2
0
        private async Task PollForQueuedTasksAsync()
        {
            CancellationToken stopToken = mStopTokenSource
                                          .Token;

            //Check cancellation token before starting
            //	the polling loop
            if (stopToken.IsCancellationRequested)
            {
                return;
            }

            while (true)
            {
                try
                {
                    //Check for token cancellation at the beginning of the loop
                    stopToken.ThrowIfCancellationRequested();

                    //If the buffer is full, we wait for some space to become available,
                    //  since, even if we can dequeue an task,
                    //  we won't have anywhere to place it yet and we
                    //  may be needlessly helding a lock to that task
                    if (mTaskBuffer.IsFull)
                    {
                        mLogger.Debug("Task buffer is full. Waiting for available space...");
                        mMetrics.UpdateMetric(AppMetricId.PollerWaitForBufferSpaceCount, m => m.Increment());
                        await mWaitForClearToAddToBuffer.ToTask();
                    }

                    //It may be that the wait handle was signaled
                    //  as part of the Stop operation,
                    //  so we need to check for that as well.
                    stopToken.ThrowIfCancellationRequested();

                    //Attempt to dequeue and then check cancellation
                    IQueuedTaskToken queuedTaskToken = await mTaskQueueConsumer
                                                       .DequeueAsync(mRequiredPayloadTypes);

                    //Before posting the token to the buffer,
                    //	check if cancellation was requested
                    stopToken.ThrowIfCancellationRequested();

                    if (queuedTaskToken != null)
                    {
                        //If we have found a token, attempt to set it as started
                        //	 and only then add it to buffer for processing.
                        //If not, dispose and discard the token
                        mLogger.DebugFormat("Task found with id = {0}, type = {1}. Acquiring reservation...",
                                            queuedTaskToken.DequeuedTask.Id,
                                            queuedTaskToken.DequeuedTask.Type);

                        mMetrics.UpdateMetric(AppMetricId.PollerDequeueCount, m => m.Increment());
                        mTaskBuffer.TryAddNewTask(queuedTaskToken);
                    }
                    else
                    {
                        //If there is no task available in the queue, begin waiting for
                        //  a notification of new added tasks
                        mLogger.Debug("No task dequeued when polled. Waiting for available task...");
                        mMetrics.UpdateMetric(AppMetricId.PollerWaitForDequeueCount, m => m.Increment());
                        await mWaitForClearToDequeue.ToTask();
                    }

                    //It may be that the wait handle was signaled
                    //  as part of the Stop operation,
                    //  so we need to check for that as well.
                    stopToken.ThrowIfCancellationRequested();

                    //Finally, reset all the handles, at the end of the loop
                    mWaitForClearToAddToBuffer.Reset();
                    mWaitForClearToDequeue.Reset();
                }
                catch (OperationCanceledException)
                {
                    mLogger.Debug("Stop requested. Breaking polling loop...");
                    break;
                }
            }

            mTaskBuffer.CompleteAdding();
        }