Ejemplo n.º 1
0
        /// <summary>Called when postponed messages may need to be consumed.</summary>
        /// <param name="isReplacementReplica">Whether this call is the continuation of a previous message loop.</param>
        internal void ConsumeAsyncIfNecessary(bool isReplacementReplica = false)
        {
            Common.ContractAssertMonitorStatus(IncomingLock, held: true);
            Debug.Assert(_boundingState != null, "Must be in bounded mode.");

            if (!_targetDecliningPermanently &&
                _boundingState.TaskForInputProcessing == null &&
                _boundingState.PostponedMessages.Count > 0 &&
                _boundingState.CountIsLessThanBound)
            {
                // Create task and store into _taskForInputProcessing prior to scheduling the task
                // so that _taskForInputProcessing will be visibly set in the task loop.
                _boundingState.TaskForInputProcessing =
                    new Task(state => ((BufferBlock <T>)state !).ConsumeMessagesLoopCore(), this,
                             Common.GetCreationOptionsForTask(isReplacementReplica));

                DataflowEtwProvider etwLog = DataflowEtwProvider.Log;
                if (etwLog.IsEnabled())
                {
                    etwLog.TaskLaunchedForMessageHandling(
                        this, _boundingState.TaskForInputProcessing, DataflowEtwProvider.TaskLaunchedReason.ProcessingInputMessages,
                        _boundingState.PostponedMessages.Count);
                }

                // Start the task handling scheduling exceptions
                Exception?exception = Common.StartTaskSafe(_boundingState.TaskForInputProcessing, _source.DataflowBlockOptions.TaskScheduler);
                if (exception != null)
                {
                    // Get out from under currently held locks. CompleteCore re-acquires the locks it needs.
                    Task.Factory.StartNew(exc => CompleteCore(exception: (Exception)exc !, storeExceptionEvenIfAlreadyCompleting: true, revertProcessingState: true),
                                          exception, CancellationToken.None, Common.GetCreationOptionsForTask(), TaskScheduler.Default);
                }
            }
        }
Ejemplo n.º 2
0
        private void CompleteBlockAsync(IList <Exception> exceptions)
        {
            Contract.Requires(_decliningPermanently, "We may get here only after we have started to decline permanently.");
            Contract.Requires(_completionReserved, "We may get here only after we have reserved completion.");
            Common.ContractAssertMonitorStatus(ValueLock, held: false);

            // If there is no exceptions list, we offer the message around, and then complete.
            // If there is an exception list, we complete without offering the message.
            if (exceptions == null)
            {
                // Offer the message to any linked targets and complete the block asynchronously to avoid blocking the caller
                var taskForOutputProcessing = new Task(state => ((WriteOnceBlock <T>)state).OfferToTargetsAndCompleteBlock(), this,
                                                       Common.GetCreationOptionsForTask());

#if FEATURE_TRACING
                DataflowEtwProvider etwLog = DataflowEtwProvider.Log;
                if (etwLog.IsEnabled())
                {
                    etwLog.TaskLaunchedForMessageHandling(
                        this, taskForOutputProcessing, DataflowEtwProvider.TaskLaunchedReason.OfferingOutputMessages, _header.IsValid ? 1 : 0);
                }
#endif

                // Start the task handling scheduling exceptions
                Exception exception = Common.StartTaskSafe(taskForOutputProcessing, _dataflowBlockOptions.TaskScheduler);
                if (exception != null)
                {
                    CompleteCore(exception, storeExceptionEvenIfAlreadyCompleting: true);
                }
            }
            else
            {
                // Complete the block asynchronously to avoid blocking the caller
                Task.Factory.StartNew(state =>
                {
                    Tuple <WriteOnceBlock <T>, IList <Exception> > blockAndList = (Tuple <WriteOnceBlock <T>, IList <Exception> >)state;
                    blockAndList.Item1.CompleteBlock(blockAndList.Item2);
                },
                                      Tuple.Create(this, exceptions), CancellationToken.None, Common.GetCreationOptionsForTask(), TaskScheduler.Default);
            }
        }