/// <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); }
//--------------------------------------------------------------------------------------- // 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); } }