Exemple #1
0
        /// <summary>Initializes the <see cref="BufferBlock{T}"/> with the specified <see cref="DataflowBlockOptions"/>.</summary>
        /// <param name="dataflowBlockOptions">The options with which to configure this <see cref="BufferBlock{T}"/>.</param>
        /// <exception cref="System.ArgumentNullException">The <paramref name="dataflowBlockOptions"/> is null (Nothing in Visual Basic).</exception>
        public BufferBlock(DataflowBlockOptions dataflowBlockOptions)
        {
            if (dataflowBlockOptions == null)
            {
                throw new ArgumentNullException("dataflowBlockOptions");
            }
            Contract.EndContractBlock();

            // Ensure we have options that can't be changed by the caller
            dataflowBlockOptions = dataflowBlockOptions.DefaultOrClone();

            // Initialize bounding state if necessary
            Action <ISourceBlock <T>, int> onItemsRemoved = null;

            if (dataflowBlockOptions.BoundedCapacity > 0)
            {
                onItemsRemoved = (owningSource, count) => ((BufferBlock <T>)owningSource).OnItemsRemoved(count);
                _boundingState = new BoundingStateWithPostponedAndTask <T>(dataflowBlockOptions.BoundedCapacity);
            }

            // Initialize the source state
            _source = new SourceCore <T>(this, dataflowBlockOptions,
                                         owningSource => ((BufferBlock <T>)owningSource).Complete(),
                                         onItemsRemoved);

            // It is possible that the source half may fault on its own, e.g. due to a task scheduler exception.
            // In those cases we need to fault the target half to drop its buffered messages and to release its
            // reservations. This should not create an infinite loop, because all our implementations are designed
            // to handle multiple completion requests and to carry over only one.
#if NET_4_0_ABOVE
            _source.Completion.ContinueWith((completed, state) =>
            {
                var thisBlock = ((BufferBlock <T>)state) as IDataflowBlock;
                Debug.Assert(completed.IsFaulted, "The source must be faulted in order to trigger a target completion.");
                thisBlock.Fault(completed.Exception);
            }, this, CancellationToken.None, Common.GetContinuationOptions() | TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
#else
            Action <Task> continuationAction = completed =>
            {
                var thisBlock = this as IDataflowBlock;
                Debug.Assert(completed.IsFaulted, "The source must be faulted in order to trigger a target completion.");
                thisBlock.Fault(completed.Exception);
            };
            _source.Completion.ContinueWith(continuationAction, CancellationToken.None, Common.GetContinuationOptions() | TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
#endif
            // Handle async cancellation requests by declining on the target
            Common.WireCancellationToComplete(
                dataflowBlockOptions.CancellationToken, _source.Completion, owningSource => ((BufferBlock <T>)owningSource).Complete(), this);
#if FEATURE_TRACING
            DataflowEtwProvider etwLog = DataflowEtwProvider.Log;
            if (etwLog.IsEnabled())
            {
                etwLog.DataflowBlockCreated(this, dataflowBlockOptions);
            }
#endif
        }
        /// <summary>Initializes the <see cref="WriteOnceBlock{T}"/> with the specified <see cref="DataflowBlockOptions"/>.</summary>
        /// <param name="cloningFunction">
        /// The function to use to clone the data when offered to other blocks.
        /// This may be null to indicate that no cloning need be performed.
        /// </param>
        /// <param name="dataflowBlockOptions">The options with which to configure this <see cref="WriteOnceBlock{T}"/>.</param>
        /// <exception cref="System.ArgumentNullException">The <paramref name="dataflowBlockOptions"/> is null (Nothing in Visual Basic).</exception>
        public WriteOnceBlock(Func <T, T> cloningFunction, DataflowBlockOptions dataflowBlockOptions)
        {
            // Validate arguments
            if (dataflowBlockOptions == null)
            {
                throw new ArgumentNullException("dataflowBlockOptions");
            }
            Contract.EndContractBlock();

            // Store the option
            _cloningFunction      = cloningFunction;
            _dataflowBlockOptions = dataflowBlockOptions.DefaultOrClone();

            // The target registry also serves as our ValueLock,
            // and thus must always be initialized, even if the block is pre-canceled, as
            // subsequent usage of the block may run through code paths that try to take this lock.
            _targetRegistry = new TargetRegistry <T>(this);

            // If a cancelable CancellationToken has been passed in,
            // we need to initialize the completion task's TCS now.
            if (dataflowBlockOptions.CancellationToken.CanBeCanceled)
            {
                _lazyCompletionTaskSource = new TaskCompletionSource <VoidResult>();

                // If we've already had cancellation requested, do as little work as we have to
                // in order to be done.
                if (dataflowBlockOptions.CancellationToken.IsCancellationRequested)
                {
                    _completionReserved = _decliningPermanently = true;

                    // Cancel the completion task's TCS
                    _lazyCompletionTaskSource.SetCanceled();
                }
                else
                {
                    // Handle async cancellation requests by declining on the target
                    Common.WireCancellationToComplete(
                        dataflowBlockOptions.CancellationToken, _lazyCompletionTaskSource.Task, state => ((WriteOnceBlock <T>)state).Complete(), this);
                }
            }
#if FEATURE_TRACING
            DataflowEtwProvider etwLog = DataflowEtwProvider.Log;
            if (etwLog.IsEnabled())
            {
                etwLog.DataflowBlockCreated(this, dataflowBlockOptions);
            }
#endif
        }