Esempio n. 1
0
        private void ScheduleConsumerIfNecessary(bool isReplica)
        {
            // If there's currently no active task...
            if (_activeConsumer == null)
            {
                // Create a new consumption task and try to set it as current as long as there's still no other task
                var newConsumer = new Task(
                    state => ((SpscTargetCore <TInput>)state).ProcessMessagesLoopCore(),
                    this, CancellationToken.None, Common.GetCreationOptionsForTask(isReplica));
                if (Interlocked.CompareExchange(ref _activeConsumer, newConsumer, null) == null)
                {
                    // We won the race.  This task is now the consumer.

#if FEATURE_TRACING
                    DataflowEtwProvider etwLog = DataflowEtwProvider.Log;
                    if (etwLog.IsEnabled())
                    {
                        etwLog.TaskLaunchedForMessageHandling(
                            _owningTarget, newConsumer, DataflowEtwProvider.TaskLaunchedReason.ProcessingInputMessages, _messages.Count);
                    }
#endif

                    // Start the task.  In the erroneous case where the scheduler throws an exception,
                    // just allow it to propagate. Our other option would be to fault the block with
                    // that exception, but in order for the block to complete we need to schedule a consumer
                    // task to do so, and it's very likely that if the scheduler is throwing an exception
                    // now, it would do so again.
                    newConsumer.Start(_dataflowBlockOptions.TaskScheduler);
                }
            }
        }
Esempio n. 2
0
        private void ProcessAsyncIfNecessary_Slow(bool repeat)
        {
            Debug.Assert(HasRoomForMoreServiceTasks, "There must be room to process asynchronously.");
            Common.ContractAssertMonitorStatus(IncomingLock, held: true);

            // Determine preconditions to launching a processing task
            bool messagesAvailableOrPostponed =
                !_messages.IsEmpty ||
                (!_decliningPermanently && _boundingState != null && _boundingState.CountIsLessThanBound && _boundingState.PostponedMessages.Count > 0);

            // If all conditions are met, launch away
            if (messagesAvailableOrPostponed && !CanceledOrFaulted)
            {
                // Any book keeping related to the processing task like incrementing the
                // DOP counter or eventually recording the tasks reference must be done
                // before the task starts. That is because the task itself will do the
                // reverse operation upon its completion.
                _numberOfOutstandingOperations++;
                if (UsesAsyncCompletion)
                {
                    _numberOfOutstandingServiceTasks++;
                }

                var taskForInputProcessing = new Task(thisTargetCore => ((TargetCore <TInput>)thisTargetCore).ProcessMessagesLoopCore(), this,
                                                      Common.GetCreationOptionsForTask(repeat));

#if FEATURE_TRACING
                DataflowEtwProvider etwLog = DataflowEtwProvider.Log;
                if (etwLog.IsEnabled())
                {
                    etwLog.TaskLaunchedForMessageHandling(
                        _owningTarget, taskForInputProcessing, DataflowEtwProvider.TaskLaunchedReason.ProcessingInputMessages,
                        _messages.Count + (_boundingState != null ? _boundingState.PostponedMessages.Count : 0));
                }
#endif

                // Start the task handling scheduling exceptions
                Exception exception = Common.StartTaskSafe(taskForInputProcessing, _dataflowBlockOptions.TaskScheduler);
                if (exception != null)
                {
                    // Get out from under currently held locks. Complete re-acquires the locks it needs.
                    Task.Factory.StartNew(exc => Complete(exception: (Exception)exc, dropPendingMessages: true, storeExceptionEvenIfAlreadyCompleting: true,
                                                          unwrapInnerExceptions: false, revertProcessingState: true),
                                          exception, CancellationToken.None, Common.GetCreationOptionsForTask(), TaskScheduler.Default);
                }
            }
        }