예제 #1
0
        /// <summary>
        /// Executes the query, either sequentially or in parallel, depending on the query execution mode and
        /// whether a premature merge was inserted by this ElementAt operator.
        /// </summary>
        /// <param name="result">result</param>
        /// <param name="withDefaultValue">withDefaultValue</param>
        /// <returns>whether an element with this index exists</returns>
        internal bool Aggregate(out TSource result, bool withDefaultValue)
        {
            // If we were to insert a premature merge before this ElementAt, and we are executing in conservative mode, run the whole query
            // sequentially.
            if (LimitsParallelism && SpecifiedQuerySettings.WithDefaults().ExecutionMode.Value != ParallelExecutionMode.ForceParallelism)
            {
                CancellationState cancelState = SpecifiedQuerySettings.CancellationState;
                if (withDefaultValue)
                {
                    IEnumerable <TSource> childAsSequential     = Child.AsSequentialQuery(cancelState.ExternalCancellationToken);
                    IEnumerable <TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, cancelState.ExternalCancellationToken);
                    result = ExceptionAggregator.WrapEnumerable(childWithCancelChecks, cancelState).ElementAtOrDefault(_index);
                }
                else
                {
                    IEnumerable <TSource> childAsSequential     = Child.AsSequentialQuery(cancelState.ExternalCancellationToken);
                    IEnumerable <TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, cancelState.ExternalCancellationToken);
                    result = ExceptionAggregator.WrapEnumerable(childWithCancelChecks, cancelState).ElementAt(_index);
                }
                return(true);
            }

            using (IEnumerator <TSource> e = GetEnumerator(ParallelMergeOptions.FullyBuffered))
            {
                if (e.MoveNext())
                {
                    TSource current = e.Current;
                    Debug.Assert(!e.MoveNext(), "expected enumerator to be empty");
                    result = current;
                    return(true);
                }
            }

            result = default(TSource);
            return(false);
        }
예제 #2
0
        //---------------------------------------------------------------------------------------
        // Executes the query and returns the results in an array.
        //

        internal TOutput[] ExecuteAndGetResultsAsArray()
        {
            QuerySettings querySettings =
                SpecifiedQuerySettings
                .WithPerExecutionSettings()
                .WithDefaults();

            QueryLifecycle.LogicalQueryExecutionBegin(querySettings.QueryId);
            try
            {
                if (querySettings.ExecutionMode.Value == ParallelExecutionMode.Default && LimitsParallelism)
                {
                    IEnumerable <TOutput> opSequential = AsSequentialQuery(querySettings.CancellationState.ExternalCancellationToken);
                    IEnumerable <TOutput> opSequentialWithCancelChecks = CancellableEnumerable.Wrap(opSequential, querySettings.CancellationState.ExternalCancellationToken);
                    return(ExceptionAggregator.WrapEnumerable(opSequentialWithCancelChecks, querySettings.CancellationState).ToArray());
                }

                QueryResults <TOutput> results = GetQueryResults(querySettings);

                // Top-level preemptive cancellation test.
                // This handles situations where cancellation has occurred before execution commences
                // The handling for in-execution occurs in QueryTaskGroupState.QueryEnd()

                if (querySettings.CancellationState.MergedCancellationToken.IsCancellationRequested)
                {
                    if (querySettings.CancellationState.ExternalCancellationToken.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(querySettings.CancellationState.ExternalCancellationToken);
                    }
                    else
                    {
                        throw new OperationCanceledException();
                    }
                }

                if (results.IsIndexible && OutputOrdered)
                {
                    // The special array-based merge performs better if the output is ordered, because
                    // it does not have to pay for ordering. In the unordered case, we it appears that
                    // the stop-and-go merge performs a little better.
                    ArrayMergeHelper <TOutput> merger = new ArrayMergeHelper <TOutput>(SpecifiedQuerySettings, results);
                    merger.Execute();
                    TOutput[] output = merger.GetResultsAsArray();
                    querySettings.CleanStateAtQueryEnd();
                    return(output);
                }
                else
                {
                    PartitionedStreamMerger <TOutput> merger =
                        new PartitionedStreamMerger <TOutput>(false, ParallelMergeOptions.FullyBuffered, querySettings.TaskScheduler,
                                                              OutputOrdered, querySettings.CancellationState, querySettings.QueryId);
                    results.GivePartitionedStream(merger);
                    TOutput[] output = merger.MergeExecutor.GetResultsAsArray();
                    querySettings.CleanStateAtQueryEnd();
                    return(output);
                }
            }
            finally
            {
                QueryLifecycle.LogicalQueryExecutionEnd(querySettings.QueryId);
            }
        }