Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Linq / Parallel / Utils / ExceptionAggregator.cs / 1305376 / ExceptionAggregator.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// ExceptionAggregator.cs
//
// [....]
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Collections.Generic;
using System.Threading;
namespace System.Linq.Parallel
{
internal static class ExceptionAggregator
{
///
/// WrapEnumerable.ExceptionAggregator wraps the enumerable with another enumerator that will
/// catch exceptions, and wrap each with an AggregateException.
///
/// If PLINQ decides to execute a query sequentially, we will reuse LINQ-to-objects
/// implementations for the different operators. However, we still need to throw
/// AggregateException in the cases when parallel execution would have thrown an
/// AggregateException. Thus, we introduce a wrapper enumerator that catches exceptions
/// and wraps them with an AggregateException.
///
internal static IEnumerable WrapEnumerable(IEnumerable source, CancellationState cancellationState)
{
using (IEnumerator enumerator = source.GetEnumerator())
{
while (true)
{
TElement elem = default(TElement);
try
{
if (!enumerator.MoveNext())
{
yield break;
}
elem = enumerator.Current;
}
catch (ThreadAbortException)
{
// Do not wrap ThreadAbortExceptions
throw;
}
catch (Exception ex)
{
ThrowOCEorAggregateException(ex, cancellationState);
}
yield return elem;
}
}
}
///
/// A variant of WrapEnumerable that accepts a QueryOperatorEnumerator{,} instead of an IEnumerable{}.
/// The code duplication is necessary to avoid extra virtual method calls that would otherwise be needed to
/// convert the QueryOperatorEnumerator{,} to an IEnumerator{}.
///
internal static IEnumerable WrapQueryEnumerator(QueryOperatorEnumerator source,
CancellationState cancellationState)
{
TElement elem = default(TElement);
TIgnoreKey ignoreKey = default(TIgnoreKey);
try
{
while (true)
{
try
{
if (!source.MoveNext(ref elem, ref ignoreKey))
{
yield break;
}
}
catch (ThreadAbortException)
{
// Do not wrap ThreadAbortExceptions
throw;
}
catch (Exception ex)
{
ThrowOCEorAggregateException(ex, cancellationState);
}
yield return elem;
}
}
finally
{
source.Dispose();
}
}
///
/// Accepts an exception, wraps it as if it was crossing the parallel->sequential boundary, and throws the
/// wrapped exception. In sequential fallback cases, we use this method to throw exceptions that are consistent
/// with exceptions thrown by PLINQ when the query is executed by worker tasks.
///
/// The exception will be wrapped into an AggregateException, except for the case when the query is being
/// legitimately cancelled, in which case we will propagate the CancellationException with the appropriate
/// token.
///
internal static void ThrowOCEorAggregateException(Exception ex, CancellationState cancellationState)
{
if (ThrowAnOCE(ex, cancellationState))
{
CancellationState.ThrowWithStandardMessageIfCanceled(
cancellationState.ExternalCancellationToken);
}
else
{
throw new AggregateException(ex);
}
}
///
/// Wraps a function with a try/catch that morphs all exceptions into AggregateException.
///
/// The input argument type.
/// The return value type.
/// A function to use internally.
/// The cancellation state to use.
/// A new function containing exception wrapping logic.
internal static Func WrapFunc(Func f, CancellationState cancellationState)
{
return t =>
{
U retval = default(U);
try
{
retval = f(t);
}
catch (ThreadAbortException)
{
// Do not wrap ThreadAbortExceptions
throw;
}
catch (Exception ex)
{
ThrowOCEorAggregateException(ex, cancellationState);
}
return retval;
};
}
// return: true ==> throw an OCE(externalCT)
// false ==> thrown an AggregateException(ex).
private static bool ThrowAnOCE(Exception ex, CancellationState cancellationState)
{
// if the query has been canceled and the exception represents this, we want to throw OCE
// but otherwise we want to throw an AggregateException to mimic normal Plinq operation
// See QueryTaskGroupState.WaitAll for the main plinq exception handling logic.
// check for co-operative cancellation.
OperationCanceledException cancelEx = ex as OperationCanceledException;
if (cancelEx != null &&
cancelEx.CancellationToken == cancellationState.ExternalCancellationToken
&& cancellationState.ExternalCancellationToken.IsCancellationRequested)
{
return true; // let the OCE(extCT) be rethrown.
}
// check for external cancellation which triggered the mergedToken.
if (cancelEx != null &&
cancelEx.CancellationToken == cancellationState.MergedCancellationToken
&& cancellationState.MergedCancellationToken.IsCancellationRequested
&& cancellationState.ExternalCancellationToken.IsCancellationRequested)
{
return true; // convert internal cancellation back to OCE(extCT).
}
return false;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// ExceptionAggregator.cs
//
// [....]
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Collections.Generic;
using System.Threading;
namespace System.Linq.Parallel
{
internal static class ExceptionAggregator
{
///
/// WrapEnumerable.ExceptionAggregator wraps the enumerable with another enumerator that will
/// catch exceptions, and wrap each with an AggregateException.
///
/// If PLINQ decides to execute a query sequentially, we will reuse LINQ-to-objects
/// implementations for the different operators. However, we still need to throw
/// AggregateException in the cases when parallel execution would have thrown an
/// AggregateException. Thus, we introduce a wrapper enumerator that catches exceptions
/// and wraps them with an AggregateException.
///
internal static IEnumerable WrapEnumerable(IEnumerable source, CancellationState cancellationState)
{
using (IEnumerator enumerator = source.GetEnumerator())
{
while (true)
{
TElement elem = default(TElement);
try
{
if (!enumerator.MoveNext())
{
yield break;
}
elem = enumerator.Current;
}
catch (ThreadAbortException)
{
// Do not wrap ThreadAbortExceptions
throw;
}
catch (Exception ex)
{
ThrowOCEorAggregateException(ex, cancellationState);
}
yield return elem;
}
}
}
///
/// A variant of WrapEnumerable that accepts a QueryOperatorEnumerator{,} instead of an IEnumerable{}.
/// The code duplication is necessary to avoid extra virtual method calls that would otherwise be needed to
/// convert the QueryOperatorEnumerator{,} to an IEnumerator{}.
///
internal static IEnumerable WrapQueryEnumerator(QueryOperatorEnumerator source,
CancellationState cancellationState)
{
TElement elem = default(TElement);
TIgnoreKey ignoreKey = default(TIgnoreKey);
try
{
while (true)
{
try
{
if (!source.MoveNext(ref elem, ref ignoreKey))
{
yield break;
}
}
catch (ThreadAbortException)
{
// Do not wrap ThreadAbortExceptions
throw;
}
catch (Exception ex)
{
ThrowOCEorAggregateException(ex, cancellationState);
}
yield return elem;
}
}
finally
{
source.Dispose();
}
}
///
/// Accepts an exception, wraps it as if it was crossing the parallel->sequential boundary, and throws the
/// wrapped exception. In sequential fallback cases, we use this method to throw exceptions that are consistent
/// with exceptions thrown by PLINQ when the query is executed by worker tasks.
///
/// The exception will be wrapped into an AggregateException, except for the case when the query is being
/// legitimately cancelled, in which case we will propagate the CancellationException with the appropriate
/// token.
///
internal static void ThrowOCEorAggregateException(Exception ex, CancellationState cancellationState)
{
if (ThrowAnOCE(ex, cancellationState))
{
CancellationState.ThrowWithStandardMessageIfCanceled(
cancellationState.ExternalCancellationToken);
}
else
{
throw new AggregateException(ex);
}
}
///
/// Wraps a function with a try/catch that morphs all exceptions into AggregateException.
///
/// The input argument type.
/// The return value type.
/// A function to use internally.
/// The cancellation state to use.
/// A new function containing exception wrapping logic.
internal static Func WrapFunc(Func f, CancellationState cancellationState)
{
return t =>
{
U retval = default(U);
try
{
retval = f(t);
}
catch (ThreadAbortException)
{
// Do not wrap ThreadAbortExceptions
throw;
}
catch (Exception ex)
{
ThrowOCEorAggregateException(ex, cancellationState);
}
return retval;
};
}
// return: true ==> throw an OCE(externalCT)
// false ==> thrown an AggregateException(ex).
private static bool ThrowAnOCE(Exception ex, CancellationState cancellationState)
{
// if the query has been canceled and the exception represents this, we want to throw OCE
// but otherwise we want to throw an AggregateException to mimic normal Plinq operation
// See QueryTaskGroupState.WaitAll for the main plinq exception handling logic.
// check for co-operative cancellation.
OperationCanceledException cancelEx = ex as OperationCanceledException;
if (cancelEx != null &&
cancelEx.CancellationToken == cancellationState.ExternalCancellationToken
&& cancellationState.ExternalCancellationToken.IsCancellationRequested)
{
return true; // let the OCE(extCT) be rethrown.
}
// check for external cancellation which triggered the mergedToken.
if (cancelEx != null &&
cancelEx.CancellationToken == cancellationState.MergedCancellationToken
&& cancellationState.MergedCancellationToken.IsCancellationRequested
&& cancellationState.ExternalCancellationToken.IsCancellationRequested)
{
return true; // convert internal cancellation back to OCE(extCT).
}
return false;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Lock.cs
- TimeoutConverter.cs
- PropagatorResult.cs
- IgnoreFileBuildProvider.cs
- EntityDesignerUtils.cs
- DataGridViewUtilities.cs
- LocalBuilder.cs
- DataGridGeneralPage.cs
- RepeaterItemCollection.cs
- ConnectionPool.cs
- HttpRequestCacheValidator.cs
- ContainerUtilities.cs
- odbcmetadatacolumnnames.cs
- IndexOutOfRangeException.cs
- TokenBasedSetEnumerator.cs
- ModelChangedEventArgsImpl.cs
- MessageTraceRecord.cs
- PolyLineSegment.cs
- ASCIIEncoding.cs
- DictionaryBase.cs
- ComponentCollection.cs
- parserscommon.cs
- SupportingTokenSpecification.cs
- StyleBamlRecordReader.cs
- RegexGroupCollection.cs
- XmlElementElement.cs
- MessageSmuggler.cs
- TargetControlTypeCache.cs
- VirtualizedContainerService.cs
- WorkflowRuntime.cs
- LogWriteRestartAreaState.cs
- HighlightVisual.cs
- SafeNativeMethods.cs
- CellQuery.cs
- LightweightCodeGenerator.cs
- SqlDataSourceCommandEventArgs.cs
- CompilerTypeWithParams.cs
- RenderOptions.cs
- TagPrefixCollection.cs
- CorrelationTokenTypeConvertor.cs
- ReadOnlyTernaryTree.cs
- CompilerGeneratedAttribute.cs
- DbParameterCollectionHelper.cs
- ToolboxBitmapAttribute.cs
- TableRowCollection.cs
- ActiveXSite.cs
- ObjectAnimationUsingKeyFrames.cs
- XamlPathDataSerializer.cs
- CodeMemberProperty.cs
- RegisteredExpandoAttribute.cs
- SettingsSection.cs
- WebPartsPersonalization.cs
- XmlSiteMapProvider.cs
- MetadataWorkspace.cs
- UserInitiatedRoutedEventPermission.cs
- ExpressionList.cs
- RowsCopiedEventArgs.cs
- UserValidatedEventArgs.cs
- NodeFunctions.cs
- StringResourceManager.cs
- ResourcePermissionBase.cs
- SpeechAudioFormatInfo.cs
- TemplateNameScope.cs
- SchemaNamespaceManager.cs
- DataGridViewRowConverter.cs
- InternalSafeNativeMethods.cs
- FastEncoder.cs
- SectionRecord.cs
- ModelPerspective.cs
- XmlNodeWriter.cs
- ProtocolImporter.cs
- AnnotationResourceChangedEventArgs.cs
- ProcessModelInfo.cs
- Substitution.cs
- ArrayWithOffset.cs
- ShutDownListener.cs
- XmlSchemaCompilationSettings.cs
- VirtualDirectoryMapping.cs
- HyperLinkField.cs
- TablePattern.cs
- SerTrace.cs
- Atom10FormatterFactory.cs
- COM2EnumConverter.cs
- RemotingConfigParser.cs
- BrowserCapabilitiesFactoryBase.cs
- StateMachineDesignerPaint.cs
- ObjectSecurity.cs
- LOSFormatter.cs
- EffectiveValueEntry.cs
- EdmFunction.cs
- WebPartMenu.cs
- PointAnimation.cs
- TypeNameHelper.cs
- XmlDataSourceNodeDescriptor.cs
- CatalogPartChrome.cs
- JsonWriter.cs
- GatewayDefinition.cs
- EndpointAddressAugust2004.cs
- XmlWriter.cs
- ColumnMapCopier.cs