Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / System.Runtime.DurableInstancing / System / Runtime / AsyncResult.cs / 1305376 / AsyncResult.cs
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Runtime
{
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Transactions;
// AsyncResult starts acquired; Complete releases.
[Fx.Tag.SynchronizationPrimitive(Fx.Tag.BlocksUsing.ManualResetEvent, SupportsAsync = true, ReleaseMethod = "Complete")]
abstract class AsyncResult : IAsyncResult
{
static AsyncCallback asyncCompletionWrapperCallback;
AsyncCallback callback;
bool completedSynchronously;
bool endCalled;
Exception exception;
bool isCompleted;
AsyncCompletion nextAsyncCompletion;
IAsyncResult deferredTransactionalResult;
TransactionSignalScope transactionContext;
object state;
[Fx.Tag.SynchronizationObject]
ManualResetEvent manualResetEvent;
[Fx.Tag.SynchronizationObject(Blocking = false)]
object thisLock;
#if DEBUG
StackTrace endStack;
StackTrace completeStack;
UncompletedAsyncResultMarker marker;
#endif
protected AsyncResult(AsyncCallback callback, object state)
{
this.callback = callback;
this.state = state;
this.thisLock = new object();
#if DEBUG
this.marker = new UncompletedAsyncResultMarker(this);
#endif
}
public object AsyncState
{
get
{
return state;
}
}
public WaitHandle AsyncWaitHandle
{
get
{
if (manualResetEvent != null)
{
return manualResetEvent;
}
lock (ThisLock)
{
if (manualResetEvent == null)
{
manualResetEvent = new ManualResetEvent(isCompleted);
}
}
return manualResetEvent;
}
}
public bool CompletedSynchronously
{
get
{
return completedSynchronously;
}
}
public bool HasCallback
{
get
{
return this.callback != null;
}
}
public bool IsCompleted
{
get
{
return isCompleted;
}
}
// used in conjunction with PrepareAsyncCompletion to allow for finally blocks
protected Action OnCompleting { get; set; }
object ThisLock
{
get
{
return this.thisLock;
}
}
// subclasses like TraceAsyncResult can use this to wrap the callback functionality in a scope
protected Action VirtualCallback
{
get;
set;
}
protected void Complete(bool completedSynchronously)
{
if (this.isCompleted)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.AsyncResultCompletedTwice(GetType())));
}
#if DEBUG
this.marker.AsyncResult = null;
this.marker = null;
if (!Fx.FastDebug && completeStack == null)
{
completeStack = new StackTrace();
}
#endif
this.completedSynchronously = completedSynchronously;
if (OnCompleting != null)
{
// Allow exception replacement, like a catch/throw pattern.
try
{
OnCompleting(this, this.exception);
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw;
}
this.exception = exception;
}
}
if (completedSynchronously)
{
// If we completedSynchronously, then there's no chance that the manualResetEvent was created so
// we don't need to worry about a ----
Fx.Assert(this.manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult.");
this.isCompleted = true;
}
else
{
lock (ThisLock)
{
this.isCompleted = true;
if (this.manualResetEvent != null)
{
this.manualResetEvent.Set();
}
}
}
if (this.callback != null)
{
try
{
if (VirtualCallback != null)
{
VirtualCallback(this.callback, this);
}
else
{
this.callback(this);
}
}
#pragma warning disable 1634
#pragma warning suppress 56500 // transferring exception to another thread
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
throw Fx.Exception.AsError(new CallbackException(SRCore.AsyncCallbackThrewException, e));
}
#pragma warning restore 1634
}
}
protected void Complete(bool completedSynchronously, Exception exception)
{
this.exception = exception;
Complete(completedSynchronously);
}
static void AsyncCompletionWrapperCallback(IAsyncResult result)
{
if (result == null)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidNullAsyncResult));
}
if (result.CompletedSynchronously)
{
return;
}
AsyncResult thisPtr = (AsyncResult)result.AsyncState;
if (thisPtr.transactionContext != null && !thisPtr.transactionContext.Signal(result))
{
// The TransactionScope isn't cleaned up yet and can't be done on this thread. Must defer
// the callback (which is likely to attempt to commit the transaction) until later.
return;
}
AsyncCompletion callback = thisPtr.GetNextCompletion();
if (callback == null)
{
ThrowInvalidAsyncResult(result);
}
bool completeSelf = false;
Exception completionException = null;
try
{
completeSelf = callback(result);
}
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
completeSelf = true;
completionException = e;
}
if (completeSelf)
{
thisPtr.Complete(false, completionException);
}
}
protected AsyncCallback PrepareAsyncCompletion(AsyncCompletion callback)
{
if (this.transactionContext != null)
{
// It might be an old, leftover one, if an exception was thrown within the last using (PrepareTransactionalCall()) block.
if (this.transactionContext.IsPotentiallyAbandoned)
{
this.transactionContext = null;
}
else
{
this.transactionContext.Prepared();
}
}
this.nextAsyncCompletion = callback;
if (AsyncResult.asyncCompletionWrapperCallback == null)
{
AsyncResult.asyncCompletionWrapperCallback = Fx.ThunkCallback(new AsyncCallback(AsyncCompletionWrapperCallback));
}
return AsyncResult.asyncCompletionWrapperCallback;
}
protected IDisposable PrepareTransactionalCall(Transaction transaction)
{
if (this.transactionContext != null && !this.transactionContext.IsPotentiallyAbandoned)
{
ThrowInvalidAsyncResult("PrepareTransactionalCall should only be called as the object of non-nested using statements. If the Begin succeeds, Check/SyncContinue must be called before another PrepareTransactionalCall.");
}
return this.transactionContext = transaction == null ? null : new TransactionSignalScope(this, transaction);
}
protected bool CheckSyncContinue(IAsyncResult result)
{
AsyncCompletion dummy;
return TryContinueHelper(result, out dummy);
}
protected bool SyncContinue(IAsyncResult result)
{
AsyncCompletion callback;
if (TryContinueHelper(result, out callback))
{
return callback(result);
}
else
{
return false;
}
}
bool TryContinueHelper(IAsyncResult result, out AsyncCompletion callback)
{
if (result == null)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidNullAsyncResult));
}
callback = null;
if (result.CompletedSynchronously)
{
// Once we pass the check, we know that we own forward progress, so transactionContext is correct. Verify its state.
if (this.transactionContext != null)
{
if (this.transactionContext.State != TransactionSignalState.Completed)
{
ThrowInvalidAsyncResult("Check/SyncContinue cannot be called from within the PrepareTransactionalCall using block.");
}
else if (this.transactionContext.IsSignalled)
{
// This is most likely to happen when result.CompletedSynchronously registers differently here and in the callback, which
// is the fault of 'result'.
ThrowInvalidAsyncResult(result);
}
}
}
else if (object.ReferenceEquals(result, this.deferredTransactionalResult))
{
// The transactionContext may not be current if forward progress has been made via the callback. Instead,
// use deferredTransactionalResult to see if we are supposed to execute a post-transaction callback.
//
// Once we pass the check, we know that we own forward progress, so transactionContext is correct. Verify its state.
if (this.transactionContext == null || !this.transactionContext.IsSignalled)
{
ThrowInvalidAsyncResult(result);
}
this.deferredTransactionalResult = null;
}
else
{
return false;
}
callback = GetNextCompletion();
if (callback == null)
{
ThrowInvalidAsyncResult("Only call Check/SyncContinue once per async operation (once per PrepareAsyncCompletion).");
}
return true;
}
AsyncCompletion GetNextCompletion()
{
AsyncCompletion result = this.nextAsyncCompletion;
this.transactionContext = null;
this.nextAsyncCompletion = null;
return result;
}
static void ThrowInvalidAsyncResult(IAsyncResult result)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidAsyncResultImplementation(result.GetType())));
}
static void ThrowInvalidAsyncResult(string debugText)
{
string message = SRCore.InvalidAsyncResultImplementationGeneric;
if (debugText != null)
{
#if DEBUG
message += " " + debugText;
#endif
}
throw Fx.Exception.AsError(new InvalidOperationException(message));
}
[Fx.Tag.Blocking(Conditional = "!asyncResult.isCompleted")]
protected static TAsyncResult End(IAsyncResult result)
where TAsyncResult : AsyncResult
{
if (result == null)
{
throw Fx.Exception.ArgumentNull("result");
}
TAsyncResult asyncResult = result as TAsyncResult;
if (asyncResult == null)
{
throw Fx.Exception.Argument("result", SRCore.InvalidAsyncResult);
}
if (asyncResult.endCalled)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.AsyncResultAlreadyEnded));
}
#if DEBUG
if (!Fx.FastDebug && asyncResult.endStack == null)
{
asyncResult.endStack = new StackTrace();
}
#endif
asyncResult.endCalled = true;
if (!asyncResult.isCompleted)
{
asyncResult.AsyncWaitHandle.WaitOne();
}
if (asyncResult.manualResetEvent != null)
{
asyncResult.manualResetEvent.Close();
}
if (asyncResult.exception != null)
{
throw Fx.Exception.AsError(asyncResult.exception);
}
return asyncResult;
}
enum TransactionSignalState
{
Ready = 0,
Prepared,
Completed,
Abandoned,
}
class TransactionSignalScope : SignalGate, IDisposable
{
TransactionScope transactionScope;
AsyncResult parent;
public TransactionSignalScope(AsyncResult result, Transaction transaction)
{
Fx.Assert(transaction != null, "Null Transaction provided to AsyncResult.TransactionSignalScope.");
this.parent = result;
this.transactionScope = Fx.CreateTransactionScope(transaction);
}
public TransactionSignalState State { get; private set; }
public bool IsPotentiallyAbandoned
{
get
{
return State == TransactionSignalState.Abandoned || (State == TransactionSignalState.Completed && !IsSignalled);
}
}
public void Prepared()
{
if (State != TransactionSignalState.Ready)
{
AsyncResult.ThrowInvalidAsyncResult("PrepareAsyncCompletion should only be called once per PrepareTransactionalCall.");
}
State = TransactionSignalState.Prepared;
}
void IDisposable.Dispose()
{
if (State == TransactionSignalState.Ready)
{
State = TransactionSignalState.Abandoned;
}
else if (State == TransactionSignalState.Prepared)
{
State = TransactionSignalState.Completed;
}
else
{
AsyncResult.ThrowInvalidAsyncResult("PrepareTransactionalCall should only be called in a using. Dispose called multiple times.");
}
try
{
Fx.CompleteTransactionScope(ref this.transactionScope);
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw;
}
// Complete and Dispose are not expected to throw. If they do it can mess up the AsyncResult state machine.
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.AsyncTransactionException));
}
// This will release the callback to run, or tell us that we need to defer the callback to Check/SyncContinue.
//
// It's possible to avoid this Interlocked when CompletedSynchronously is true, but we have no way of knowing that
// from here, and adding a way would add complexity to the AsyncResult transactional calling pattern. This
// unnecessary Interlocked only happens when: PrepareTransactionalCall is called with a non-null transaction,
// PrepareAsyncCompletion is reached, and the operation completes synchronously or with an exception.
IAsyncResult result;
if (State == TransactionSignalState.Completed && Unlock(out result))
{
if (this.parent.deferredTransactionalResult != null)
{
AsyncResult.ThrowInvalidAsyncResult(this.parent.deferredTransactionalResult);
}
this.parent.deferredTransactionalResult = result;
}
}
}
// can be utilized by subclasses to write core completion code for both the [....] and async paths
// in one location, signalling chainable synchronous completion with the boolean result,
// and leveraging PrepareAsyncCompletion for conversion to an AsyncCallback.
// NOTE: requires that "this" is passed in as the state object to the asynchronous sub-call being used with a completion routine.
protected delegate bool AsyncCompletion(IAsyncResult result);
#if DEBUG
class UncompletedAsyncResultMarker
{
public UncompletedAsyncResultMarker(AsyncResult result)
{
AsyncResult = result;
}
[SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode,
Justification = "Debug-only facility")]
public AsyncResult AsyncResult { get; set; }
}
#endif
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Runtime
{
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Transactions;
// AsyncResult starts acquired; Complete releases.
[Fx.Tag.SynchronizationPrimitive(Fx.Tag.BlocksUsing.ManualResetEvent, SupportsAsync = true, ReleaseMethod = "Complete")]
abstract class AsyncResult : IAsyncResult
{
static AsyncCallback asyncCompletionWrapperCallback;
AsyncCallback callback;
bool completedSynchronously;
bool endCalled;
Exception exception;
bool isCompleted;
AsyncCompletion nextAsyncCompletion;
IAsyncResult deferredTransactionalResult;
TransactionSignalScope transactionContext;
object state;
[Fx.Tag.SynchronizationObject]
ManualResetEvent manualResetEvent;
[Fx.Tag.SynchronizationObject(Blocking = false)]
object thisLock;
#if DEBUG
StackTrace endStack;
StackTrace completeStack;
UncompletedAsyncResultMarker marker;
#endif
protected AsyncResult(AsyncCallback callback, object state)
{
this.callback = callback;
this.state = state;
this.thisLock = new object();
#if DEBUG
this.marker = new UncompletedAsyncResultMarker(this);
#endif
}
public object AsyncState
{
get
{
return state;
}
}
public WaitHandle AsyncWaitHandle
{
get
{
if (manualResetEvent != null)
{
return manualResetEvent;
}
lock (ThisLock)
{
if (manualResetEvent == null)
{
manualResetEvent = new ManualResetEvent(isCompleted);
}
}
return manualResetEvent;
}
}
public bool CompletedSynchronously
{
get
{
return completedSynchronously;
}
}
public bool HasCallback
{
get
{
return this.callback != null;
}
}
public bool IsCompleted
{
get
{
return isCompleted;
}
}
// used in conjunction with PrepareAsyncCompletion to allow for finally blocks
protected Action OnCompleting { get; set; }
object ThisLock
{
get
{
return this.thisLock;
}
}
// subclasses like TraceAsyncResult can use this to wrap the callback functionality in a scope
protected Action VirtualCallback
{
get;
set;
}
protected void Complete(bool completedSynchronously)
{
if (this.isCompleted)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.AsyncResultCompletedTwice(GetType())));
}
#if DEBUG
this.marker.AsyncResult = null;
this.marker = null;
if (!Fx.FastDebug && completeStack == null)
{
completeStack = new StackTrace();
}
#endif
this.completedSynchronously = completedSynchronously;
if (OnCompleting != null)
{
// Allow exception replacement, like a catch/throw pattern.
try
{
OnCompleting(this, this.exception);
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw;
}
this.exception = exception;
}
}
if (completedSynchronously)
{
// If we completedSynchronously, then there's no chance that the manualResetEvent was created so
// we don't need to worry about a ----
Fx.Assert(this.manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult.");
this.isCompleted = true;
}
else
{
lock (ThisLock)
{
this.isCompleted = true;
if (this.manualResetEvent != null)
{
this.manualResetEvent.Set();
}
}
}
if (this.callback != null)
{
try
{
if (VirtualCallback != null)
{
VirtualCallback(this.callback, this);
}
else
{
this.callback(this);
}
}
#pragma warning disable 1634
#pragma warning suppress 56500 // transferring exception to another thread
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
throw Fx.Exception.AsError(new CallbackException(SRCore.AsyncCallbackThrewException, e));
}
#pragma warning restore 1634
}
}
protected void Complete(bool completedSynchronously, Exception exception)
{
this.exception = exception;
Complete(completedSynchronously);
}
static void AsyncCompletionWrapperCallback(IAsyncResult result)
{
if (result == null)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidNullAsyncResult));
}
if (result.CompletedSynchronously)
{
return;
}
AsyncResult thisPtr = (AsyncResult)result.AsyncState;
if (thisPtr.transactionContext != null && !thisPtr.transactionContext.Signal(result))
{
// The TransactionScope isn't cleaned up yet and can't be done on this thread. Must defer
// the callback (which is likely to attempt to commit the transaction) until later.
return;
}
AsyncCompletion callback = thisPtr.GetNextCompletion();
if (callback == null)
{
ThrowInvalidAsyncResult(result);
}
bool completeSelf = false;
Exception completionException = null;
try
{
completeSelf = callback(result);
}
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
completeSelf = true;
completionException = e;
}
if (completeSelf)
{
thisPtr.Complete(false, completionException);
}
}
protected AsyncCallback PrepareAsyncCompletion(AsyncCompletion callback)
{
if (this.transactionContext != null)
{
// It might be an old, leftover one, if an exception was thrown within the last using (PrepareTransactionalCall()) block.
if (this.transactionContext.IsPotentiallyAbandoned)
{
this.transactionContext = null;
}
else
{
this.transactionContext.Prepared();
}
}
this.nextAsyncCompletion = callback;
if (AsyncResult.asyncCompletionWrapperCallback == null)
{
AsyncResult.asyncCompletionWrapperCallback = Fx.ThunkCallback(new AsyncCallback(AsyncCompletionWrapperCallback));
}
return AsyncResult.asyncCompletionWrapperCallback;
}
protected IDisposable PrepareTransactionalCall(Transaction transaction)
{
if (this.transactionContext != null && !this.transactionContext.IsPotentiallyAbandoned)
{
ThrowInvalidAsyncResult("PrepareTransactionalCall should only be called as the object of non-nested using statements. If the Begin succeeds, Check/SyncContinue must be called before another PrepareTransactionalCall.");
}
return this.transactionContext = transaction == null ? null : new TransactionSignalScope(this, transaction);
}
protected bool CheckSyncContinue(IAsyncResult result)
{
AsyncCompletion dummy;
return TryContinueHelper(result, out dummy);
}
protected bool SyncContinue(IAsyncResult result)
{
AsyncCompletion callback;
if (TryContinueHelper(result, out callback))
{
return callback(result);
}
else
{
return false;
}
}
bool TryContinueHelper(IAsyncResult result, out AsyncCompletion callback)
{
if (result == null)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidNullAsyncResult));
}
callback = null;
if (result.CompletedSynchronously)
{
// Once we pass the check, we know that we own forward progress, so transactionContext is correct. Verify its state.
if (this.transactionContext != null)
{
if (this.transactionContext.State != TransactionSignalState.Completed)
{
ThrowInvalidAsyncResult("Check/SyncContinue cannot be called from within the PrepareTransactionalCall using block.");
}
else if (this.transactionContext.IsSignalled)
{
// This is most likely to happen when result.CompletedSynchronously registers differently here and in the callback, which
// is the fault of 'result'.
ThrowInvalidAsyncResult(result);
}
}
}
else if (object.ReferenceEquals(result, this.deferredTransactionalResult))
{
// The transactionContext may not be current if forward progress has been made via the callback. Instead,
// use deferredTransactionalResult to see if we are supposed to execute a post-transaction callback.
//
// Once we pass the check, we know that we own forward progress, so transactionContext is correct. Verify its state.
if (this.transactionContext == null || !this.transactionContext.IsSignalled)
{
ThrowInvalidAsyncResult(result);
}
this.deferredTransactionalResult = null;
}
else
{
return false;
}
callback = GetNextCompletion();
if (callback == null)
{
ThrowInvalidAsyncResult("Only call Check/SyncContinue once per async operation (once per PrepareAsyncCompletion).");
}
return true;
}
AsyncCompletion GetNextCompletion()
{
AsyncCompletion result = this.nextAsyncCompletion;
this.transactionContext = null;
this.nextAsyncCompletion = null;
return result;
}
static void ThrowInvalidAsyncResult(IAsyncResult result)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidAsyncResultImplementation(result.GetType())));
}
static void ThrowInvalidAsyncResult(string debugText)
{
string message = SRCore.InvalidAsyncResultImplementationGeneric;
if (debugText != null)
{
#if DEBUG
message += " " + debugText;
#endif
}
throw Fx.Exception.AsError(new InvalidOperationException(message));
}
[Fx.Tag.Blocking(Conditional = "!asyncResult.isCompleted")]
protected static TAsyncResult End(IAsyncResult result)
where TAsyncResult : AsyncResult
{
if (result == null)
{
throw Fx.Exception.ArgumentNull("result");
}
TAsyncResult asyncResult = result as TAsyncResult;
if (asyncResult == null)
{
throw Fx.Exception.Argument("result", SRCore.InvalidAsyncResult);
}
if (asyncResult.endCalled)
{
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.AsyncResultAlreadyEnded));
}
#if DEBUG
if (!Fx.FastDebug && asyncResult.endStack == null)
{
asyncResult.endStack = new StackTrace();
}
#endif
asyncResult.endCalled = true;
if (!asyncResult.isCompleted)
{
asyncResult.AsyncWaitHandle.WaitOne();
}
if (asyncResult.manualResetEvent != null)
{
asyncResult.manualResetEvent.Close();
}
if (asyncResult.exception != null)
{
throw Fx.Exception.AsError(asyncResult.exception);
}
return asyncResult;
}
enum TransactionSignalState
{
Ready = 0,
Prepared,
Completed,
Abandoned,
}
class TransactionSignalScope : SignalGate, IDisposable
{
TransactionScope transactionScope;
AsyncResult parent;
public TransactionSignalScope(AsyncResult result, Transaction transaction)
{
Fx.Assert(transaction != null, "Null Transaction provided to AsyncResult.TransactionSignalScope.");
this.parent = result;
this.transactionScope = Fx.CreateTransactionScope(transaction);
}
public TransactionSignalState State { get; private set; }
public bool IsPotentiallyAbandoned
{
get
{
return State == TransactionSignalState.Abandoned || (State == TransactionSignalState.Completed && !IsSignalled);
}
}
public void Prepared()
{
if (State != TransactionSignalState.Ready)
{
AsyncResult.ThrowInvalidAsyncResult("PrepareAsyncCompletion should only be called once per PrepareTransactionalCall.");
}
State = TransactionSignalState.Prepared;
}
void IDisposable.Dispose()
{
if (State == TransactionSignalState.Ready)
{
State = TransactionSignalState.Abandoned;
}
else if (State == TransactionSignalState.Prepared)
{
State = TransactionSignalState.Completed;
}
else
{
AsyncResult.ThrowInvalidAsyncResult("PrepareTransactionalCall should only be called in a using. Dispose called multiple times.");
}
try
{
Fx.CompleteTransactionScope(ref this.transactionScope);
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw;
}
// Complete and Dispose are not expected to throw. If they do it can mess up the AsyncResult state machine.
throw Fx.Exception.AsError(new InvalidOperationException(SRCore.AsyncTransactionException));
}
// This will release the callback to run, or tell us that we need to defer the callback to Check/SyncContinue.
//
// It's possible to avoid this Interlocked when CompletedSynchronously is true, but we have no way of knowing that
// from here, and adding a way would add complexity to the AsyncResult transactional calling pattern. This
// unnecessary Interlocked only happens when: PrepareTransactionalCall is called with a non-null transaction,
// PrepareAsyncCompletion is reached, and the operation completes synchronously or with an exception.
IAsyncResult result;
if (State == TransactionSignalState.Completed && Unlock(out result))
{
if (this.parent.deferredTransactionalResult != null)
{
AsyncResult.ThrowInvalidAsyncResult(this.parent.deferredTransactionalResult);
}
this.parent.deferredTransactionalResult = result;
}
}
}
// can be utilized by subclasses to write core completion code for both the [....] and async paths
// in one location, signalling chainable synchronous completion with the boolean result,
// and leveraging PrepareAsyncCompletion for conversion to an AsyncCallback.
// NOTE: requires that "this" is passed in as the state object to the asynchronous sub-call being used with a completion routine.
protected delegate bool AsyncCompletion(IAsyncResult result);
#if DEBUG
class UncompletedAsyncResultMarker
{
public UncompletedAsyncResultMarker(AsyncResult result)
{
AsyncResult = result;
}
[SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode,
Justification = "Debug-only facility")]
public AsyncResult AsyncResult { get; set; }
}
#endif
}
}
// 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
- DataGridRowDetailsEventArgs.cs
- ParameterCollection.cs
- DBCommandBuilder.cs
- RouteItem.cs
- InboundActivityHelper.cs
- FieldToken.cs
- SqlGatherProducedAliases.cs
- JsonEncodingStreamWrapper.cs
- TextCompositionManager.cs
- ExpressionDumper.cs
- HttpWebRequestElement.cs
- x509store.cs
- SecurityElement.cs
- UInt16Storage.cs
- DESCryptoServiceProvider.cs
- activationcontext.cs
- MsmqIntegrationProcessProtocolHandler.cs
- WorkflowFileItem.cs
- CheckBoxFlatAdapter.cs
- DataServiceContext.cs
- JavaScriptString.cs
- CounterCreationData.cs
- Calendar.cs
- ellipse.cs
- RouteParameter.cs
- HierarchicalDataBoundControl.cs
- MissingFieldException.cs
- UnknownBitmapDecoder.cs
- BinaryReader.cs
- IdentityNotMappedException.cs
- IPPacketInformation.cs
- IntPtr.cs
- ProviderException.cs
- MustUnderstandSoapException.cs
- ComponentEditorPage.cs
- TextTreeUndo.cs
- EventlogProvider.cs
- HierarchicalDataSourceControl.cs
- SafeLocalAllocation.cs
- RegionIterator.cs
- XmlResolver.cs
- PrintDialog.cs
- ClientSession.cs
- WebPartTransformer.cs
- PackageFilter.cs
- WebPartCatalogCloseVerb.cs
- PhysicalFontFamily.cs
- Root.cs
- XmlSerializerImportOptions.cs
- FormsAuthentication.cs
- XmlSerializationGeneratedCode.cs
- mediaeventshelper.cs
- HostExecutionContextManager.cs
- WmiPutTraceRecord.cs
- TextInfo.cs
- ComponentConverter.cs
- LayoutTableCell.cs
- DbParameterCollectionHelper.cs
- Currency.cs
- InputBuffer.cs
- TreeNodeBinding.cs
- DataGridItem.cs
- IncrementalHitTester.cs
- MethodCallExpression.cs
- Transform3DCollection.cs
- DrawingDrawingContext.cs
- CanExecuteRoutedEventArgs.cs
- TextParagraph.cs
- SqlXml.cs
- MatrixUtil.cs
- GACIdentityPermission.cs
- PackUriHelper.cs
- IndependentAnimationStorage.cs
- _AcceptOverlappedAsyncResult.cs
- CommandArguments.cs
- InsufficientMemoryException.cs
- SmiEventSink_Default.cs
- TemplateBindingExtension.cs
- BinaryMessageEncodingBindingElement.cs
- OracleString.cs
- GridEntry.cs
- XamlGridLengthSerializer.cs
- NativeStructs.cs
- SoapFormatterSinks.cs
- HttpRequestCacheValidator.cs
- SqlBuilder.cs
- GridViewItemAutomationPeer.cs
- AssemblyHash.cs
- IdentifierService.cs
- SharedConnectionWorkflowTransactionService.cs
- HttpHeaderCollection.cs
- XhtmlConformanceSection.cs
- AnchoredBlock.cs
- DataControlPagerLinkButton.cs
- InternalConfigSettingsFactory.cs
- UserControlCodeDomTreeGenerator.cs
- ReferentialConstraint.cs
- LayoutManager.cs
- If.cs
- IsolatedStoragePermission.cs