Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Threading / Tasks / TaskExtensions.cs / 1305376 / TaskExtensions.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// TaskExtensions.cs
//
// [....]
//
// Extensions to Task/Task classes
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics.Contracts;
namespace System.Threading.Tasks
{
///
/// Provides a set of static (Shared in Visual Basic) methods for working with specific kinds of
/// instances.
///
public static class TaskExtensions
{
///
/// Creates a proxy Task that represents the
/// asynchronous operation of a Task{Task}.
///
///
/// It is often useful to be able to return a Task from a
/// Task{TResult} , where the inner Task represents work done as part of the outer Task{TResult}. However,
/// doing so results in a Task{Task}, which, if not dealt with carefully, could produce unexpected behavior. Unwrap
/// solves this problem by creating a proxy Task that represents the entire asynchronous operation of such a Task{Task}.
///
/// The Task{Task} to unwrap.
/// The exception that is thrown if the
/// argument is null.
/// A Task that represents the asynchronous operation of the provided Task{Task}.
public static Task Unwrap(this Task task)
{
if (task == null) throw new ArgumentNullException("task");
bool result;
// tcs.Task serves as a proxy for task.Result.
// AttachedToParent is the only legal option for TCS-style task.
var tcs = new TaskCompletionSource(task.CreationOptions & TaskCreationOptions.AttachedToParent);
// Set up some actions to take when task has completed.
task.ContinueWith(delegate
{
switch (task.Status)
{
// If task did not run to completion, then record the cancellation/fault information
// to tcs.Task.
case TaskStatus.Canceled:
case TaskStatus.Faulted:
result = tcs.TrySetFromTask(task);
Contract.Assert(result, "Unwrap(Task): Expected TrySetFromTask #1 to succeed");
break;
case TaskStatus.RanToCompletion:
// task.Result == null ==> proxy should be canceled.
if (task.Result == null) tcs.TrySetCanceled();
// When task.Result completes, take some action to set the completion state of tcs.Task.
else
{
task.Result.ContinueWith(_ =>
{
// Copy completion/cancellation/exception info from task.Result to tcs.Task.
result = tcs.TrySetFromTask(task.Result);
Contract.Assert(result, "Unwrap(Task): Expected TrySetFromTask #2 to succeed");
}, TaskContinuationOptions.ExecuteSynchronously).ContinueWith(antecedent =>
{
// Clean up if ContinueWith() operation fails due to TSE
tcs.TrySetException(antecedent.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
}
break;
}
}, TaskContinuationOptions.ExecuteSynchronously).ContinueWith(antecedent =>
{
// Clean up if ContinueWith() operation fails due to TSE
tcs.TrySetException(antecedent.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
// Return this immediately as a proxy. When task.Result completes, or task is faulted/canceled,
// the completion information will be transfered to tcs.Task.
return tcs.Task;
}
///
/// Creates a proxy Task{TResult} that represents the
/// asynchronous operation of a Task{Task{TResult}}.
///
///
/// It is often useful to be able to return a Task{TResult} from a Task{TResult}, where the inner Task{TResult}
/// represents work done as part of the outer Task{TResult}. However, doing so results in a Task{Task{TResult}},
/// which, if not dealt with carefully, could produce unexpected behavior. Unwrap solves this problem by
/// creating a proxy Task{TResult} that represents the entire asynchronous operation of such a Task{Task{TResult}}.
///
/// The Task{Task{TResult}} to unwrap.
/// The exception that is thrown if the
/// argument is null.
/// A Task{TResult} that represents the asynchronous operation of the provided Task{Task{TResult}}. /// Unwraps a Task that returns another Task.
public static Task Unwrap(this Task> task)
{
if (task == null) throw new ArgumentNullException("task");
bool result;
// tcs.Task serves as a proxy for task.Result.
// AttachedToParent is the only legal option for TCS-style task.
var tcs = new TaskCompletionSource(task.CreationOptions & TaskCreationOptions.AttachedToParent);
// Set up some actions to take when task has completed.
task.ContinueWith(delegate
{
switch (task.Status)
{
// If task did not run to completion, then record the cancellation/fault information
// to tcs.Task.
case TaskStatus.Canceled:
case TaskStatus.Faulted:
result = tcs.TrySetFromTask(task);
Contract.Assert(result, "Unwrap(Task>): Expected TrySetFromTask #1 to succeed");
break;
case TaskStatus.RanToCompletion:
// task.Result == null ==> proxy should be canceled.
if (task.Result == null) tcs.TrySetCanceled();
// When task.Result completes, take some action to set the completion state of tcs.Task.
else
{
task.Result.ContinueWith(_ =>
{
// Copy completion/cancellation/exception info from task.Result to tcs.Task.
result = tcs.TrySetFromTask(task.Result);
Contract.Assert(result, "Unwrap(Task>): Expected TrySetFromTask #2 to succeed");
},
TaskContinuationOptions.ExecuteSynchronously).ContinueWith(antecedent =>
{
// Clean up if ContinueWith() operation fails due to TSE
tcs.TrySetException(antecedent.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
}
break;
}
}, TaskContinuationOptions.ExecuteSynchronously).ContinueWith(antecedent =>
{
// Clean up if ContinueWith() operation fails due to TSE
tcs.TrySetException(antecedent.Exception);
}, TaskContinuationOptions.OnlyOnFaulted); ;
// Return this immediately as a proxy. When task.Result completes, or task is faulted/canceled,
// the completion information will be transfered to tcs.Task.
return tcs.Task;
}
// Transfer the completion status from "source" to "me".
private static bool TrySetFromTask(this TaskCompletionSource me, Task source)
{
Contract.Assert(source.IsCompleted, "TrySetFromTask: Expected source to have completed.");
bool rval = false;
switch(source.Status)
{
case TaskStatus.Canceled:
rval = me.TrySetCanceled();
break;
case TaskStatus.Faulted:
rval = me.TrySetException(source.Exception.InnerExceptions);
break;
case TaskStatus.RanToCompletion:
if(source is Task)
rval = me.TrySetResult( ((Task)source).Result);
else
rval = me.TrySetResult(default(TResult));
break;
}
return rval;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// TaskExtensions.cs
//
// [....]
//
// Extensions to Task/Task classes
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics.Contracts;
namespace System.Threading.Tasks
{
///
/// Provides a set of static (Shared in Visual Basic) methods for working with specific kinds of
/// instances.
///
public static class TaskExtensions
{
///
/// Creates a proxy Task that represents the
/// asynchronous operation of a Task{Task}.
///
///
/// It is often useful to be able to return a Task from a
/// Task{TResult} , where the inner Task represents work done as part of the outer Task{TResult}. However,
/// doing so results in a Task{Task}, which, if not dealt with carefully, could produce unexpected behavior. Unwrap
/// solves this problem by creating a proxy Task that represents the entire asynchronous operation of such a Task{Task}.
///
/// The Task{Task} to unwrap.
/// The exception that is thrown if the
/// argument is null.
/// A Task that represents the asynchronous operation of the provided Task{Task}.
public static Task Unwrap(this Task task)
{
if (task == null) throw new ArgumentNullException("task");
bool result;
// tcs.Task serves as a proxy for task.Result.
// AttachedToParent is the only legal option for TCS-style task.
var tcs = new TaskCompletionSource(task.CreationOptions & TaskCreationOptions.AttachedToParent);
// Set up some actions to take when task has completed.
task.ContinueWith(delegate
{
switch (task.Status)
{
// If task did not run to completion, then record the cancellation/fault information
// to tcs.Task.
case TaskStatus.Canceled:
case TaskStatus.Faulted:
result = tcs.TrySetFromTask(task);
Contract.Assert(result, "Unwrap(Task): Expected TrySetFromTask #1 to succeed");
break;
case TaskStatus.RanToCompletion:
// task.Result == null ==> proxy should be canceled.
if (task.Result == null) tcs.TrySetCanceled();
// When task.Result completes, take some action to set the completion state of tcs.Task.
else
{
task.Result.ContinueWith(_ =>
{
// Copy completion/cancellation/exception info from task.Result to tcs.Task.
result = tcs.TrySetFromTask(task.Result);
Contract.Assert(result, "Unwrap(Task): Expected TrySetFromTask #2 to succeed");
}, TaskContinuationOptions.ExecuteSynchronously).ContinueWith(antecedent =>
{
// Clean up if ContinueWith() operation fails due to TSE
tcs.TrySetException(antecedent.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
}
break;
}
}, TaskContinuationOptions.ExecuteSynchronously).ContinueWith(antecedent =>
{
// Clean up if ContinueWith() operation fails due to TSE
tcs.TrySetException(antecedent.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
// Return this immediately as a proxy. When task.Result completes, or task is faulted/canceled,
// the completion information will be transfered to tcs.Task.
return tcs.Task;
}
///
/// Creates a proxy Task{TResult} that represents the
/// asynchronous operation of a Task{Task{TResult}}.
///
///
/// It is often useful to be able to return a Task{TResult} from a Task{TResult}, where the inner Task{TResult}
/// represents work done as part of the outer Task{TResult}. However, doing so results in a Task{Task{TResult}},
/// which, if not dealt with carefully, could produce unexpected behavior. Unwrap solves this problem by
/// creating a proxy Task{TResult} that represents the entire asynchronous operation of such a Task{Task{TResult}}.
///
/// The Task{Task{TResult}} to unwrap.
/// The exception that is thrown if the
/// argument is null.
/// A Task{TResult} that represents the asynchronous operation of the provided Task{Task{TResult}}. /// Unwraps a Task that returns another Task.
public static Task Unwrap(this Task> task)
{
if (task == null) throw new ArgumentNullException("task");
bool result;
// tcs.Task serves as a proxy for task.Result.
// AttachedToParent is the only legal option for TCS-style task.
var tcs = new TaskCompletionSource(task.CreationOptions & TaskCreationOptions.AttachedToParent);
// Set up some actions to take when task has completed.
task.ContinueWith(delegate
{
switch (task.Status)
{
// If task did not run to completion, then record the cancellation/fault information
// to tcs.Task.
case TaskStatus.Canceled:
case TaskStatus.Faulted:
result = tcs.TrySetFromTask(task);
Contract.Assert(result, "Unwrap(Task>): Expected TrySetFromTask #1 to succeed");
break;
case TaskStatus.RanToCompletion:
// task.Result == null ==> proxy should be canceled.
if (task.Result == null) tcs.TrySetCanceled();
// When task.Result completes, take some action to set the completion state of tcs.Task.
else
{
task.Result.ContinueWith(_ =>
{
// Copy completion/cancellation/exception info from task.Result to tcs.Task.
result = tcs.TrySetFromTask(task.Result);
Contract.Assert(result, "Unwrap(Task>): Expected TrySetFromTask #2 to succeed");
},
TaskContinuationOptions.ExecuteSynchronously).ContinueWith(antecedent =>
{
// Clean up if ContinueWith() operation fails due to TSE
tcs.TrySetException(antecedent.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
}
break;
}
}, TaskContinuationOptions.ExecuteSynchronously).ContinueWith(antecedent =>
{
// Clean up if ContinueWith() operation fails due to TSE
tcs.TrySetException(antecedent.Exception);
}, TaskContinuationOptions.OnlyOnFaulted); ;
// Return this immediately as a proxy. When task.Result completes, or task is faulted/canceled,
// the completion information will be transfered to tcs.Task.
return tcs.Task;
}
// Transfer the completion status from "source" to "me".
private static bool TrySetFromTask(this TaskCompletionSource me, Task source)
{
Contract.Assert(source.IsCompleted, "TrySetFromTask: Expected source to have completed.");
bool rval = false;
switch(source.Status)
{
case TaskStatus.Canceled:
rval = me.TrySetCanceled();
break;
case TaskStatus.Faulted:
rval = me.TrySetException(source.Exception.InnerExceptions);
break;
case TaskStatus.RanToCompletion:
if(source is Task)
rval = me.TrySetResult( ((Task)source).Result);
else
rval = me.TrySetResult(default(TResult));
break;
}
return rval;
}
}
}
// 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
- DataSetMappper.cs
- WebPartConnection.cs
- GenericWebPart.cs
- PropertyGrid.cs
- WebPartConnectionsCloseVerb.cs
- PresentationSource.cs
- DataGridViewComponentPropertyGridSite.cs
- LowerCaseStringConverter.cs
- ObjectFullSpanRewriter.cs
- FtpWebResponse.cs
- Menu.cs
- httpapplicationstate.cs
- LinkUtilities.cs
- XmlWrappingReader.cs
- SubMenuStyle.cs
- MinimizableAttributeTypeConverter.cs
- XmlSubtreeReader.cs
- DataMemberAttribute.cs
- StringFormat.cs
- TransactionChannelFaultConverter.cs
- SafeArrayTypeMismatchException.cs
- DesignSurfaceCollection.cs
- WebPartConnectionsCancelEventArgs.cs
- XmlTypeAttribute.cs
- RoutedPropertyChangedEventArgs.cs
- RequestResponse.cs
- HttpCookiesSection.cs
- StartUpEventArgs.cs
- ApplicationTrust.cs
- Oid.cs
- SoapReflectionImporter.cs
- WebPartTransformerCollection.cs
- XmlSchemaException.cs
- FreezableOperations.cs
- WebRequestModuleElement.cs
- DBCommand.cs
- MarkupObject.cs
- OleDbSchemaGuid.cs
- SqlRowUpdatedEvent.cs
- HttpHeaderCollection.cs
- AppDomainAttributes.cs
- Registry.cs
- APCustomTypeDescriptor.cs
- XsdDuration.cs
- StrongName.cs
- HtmlSelect.cs
- Bitmap.cs
- UnsafeNativeMethods.cs
- CookieParameter.cs
- UserValidatedEventArgs.cs
- DocumentAutomationPeer.cs
- ToolStripOverflow.cs
- DynamicValueConverter.cs
- UIAgentAsyncParams.cs
- TextTreeText.cs
- Annotation.cs
- XmlIlGenerator.cs
- DataGridViewTextBoxColumn.cs
- AttributedMetaModel.cs
- StreamInfo.cs
- SqlDataSourceEnumerator.cs
- pingexception.cs
- OperatorExpressions.cs
- DependencyObjectType.cs
- CapabilitiesRule.cs
- AnnouncementService.cs
- DodSequenceMerge.cs
- XmlConverter.cs
- Brush.cs
- DesignerUtility.cs
- ItemCollection.cs
- XPathNodeInfoAtom.cs
- DecimalStorage.cs
- OdbcRowUpdatingEvent.cs
- EventLogLink.cs
- AutomationTextAttribute.cs
- HatchBrush.cs
- MobileControlsSection.cs
- TemplateXamlParser.cs
- Literal.cs
- CompositeActivityDesigner.cs
- KnownBoxes.cs
- SeverityFilter.cs
- DataKey.cs
- MouseWheelEventArgs.cs
- GradientStopCollection.cs
- DbConnectionHelper.cs
- DataGridViewSelectedCellCollection.cs
- DeferredBinaryDeserializerExtension.cs
- JapaneseLunisolarCalendar.cs
- IndexedWhereQueryOperator.cs
- SchemaElementLookUpTable.cs
- XmlSecureResolver.cs
- ProxyManager.cs
- ReferencedAssemblyResolver.cs
- TableProviderWrapper.cs
- StructuredProperty.cs
- DataBindEngine.cs
- GridSplitter.cs
- ActionItem.cs