1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System.IdentityModel
8 using System.Diagnostics;
9 using System.Threading;
13 /// Base class for common AsyncResult programming scenarios.
15 public abstract class AsyncResult : IAsyncResult, IDisposable
18 /// End should be called when the End function for the asynchronous operation is complete. It
19 /// ensures the asynchronous operation is complete, and does some common validation.
21 /// <param name="result">The <see cref="IAsyncResult"/> representing the status of an asynchronous operation.</param>
22 public static void End(IAsyncResult result)
25 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("result");
27 AsyncResult asyncResult = result as AsyncResult;
29 if (asyncResult == null)
30 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.ID4001), "result"));
32 if (asyncResult.endCalled)
33 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4002)));
35 asyncResult.endCalled = true;
37 if (!asyncResult.completed)
38 asyncResult.AsyncWaitHandle.WaitOne();
40 if (asyncResult.resetEvent != null)
41 ((IDisposable)asyncResult.resetEvent).Dispose();
43 if (asyncResult.exception != null)
44 throw asyncResult.exception;
47 AsyncCallback callback;
53 ManualResetEvent resetEvent;
59 /// Constructor for async results that do not need a callback or state.
61 protected AsyncResult()
67 /// Constructor for async results that do not need a callback.
69 /// <param name="state">A user-defined object that qualifies or contains information about an asynchronous operation.</param>
70 protected AsyncResult(object state)
76 /// Constructor for async results that need a callback and a state.
78 /// <param name="callback">The method to be called when the async operation completes.</param>
79 /// <param name="state">A user-defined object that qualifies or contains information about an asynchronous operation.</param>
80 protected AsyncResult(AsyncCallback callback, object state)
82 this.thisLock = new object();
83 this.callback = callback;
88 /// Finalizer for AsyncResult.
96 /// Call this version of complete when your asynchronous operation is complete. This will update the state
97 /// of the operation and notify the callback.
99 /// <param name="completedSynchronously">True if the asynchronous operation completed synchronously.</param>
100 protected void Complete(bool completedSynchronously)
102 Complete(completedSynchronously, null);
106 /// Call this version of complete if you raise an exception during processing. In addition to notifying
107 /// the callback, it will capture the exception and store it to be thrown during AsyncResult.End.
109 /// <param name="completedSynchronously">True if the asynchronous operation completed synchronously.</param>
110 /// <param name="exception">The exception during the processing of the asynchronous operation.</param>
111 protected void Complete(bool completedSynchronously, Exception exception)
113 if (completed == true)
115 // it is a bug to call complete twice
116 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AsynchronousOperationException(SR.GetString(SR.ID4005)));
119 completedSync = completedSynchronously;
120 this.exception = exception;
122 if (completedSynchronously)
125 // No event should be set for synchronous completion
128 Fx.Assert(resetEvent == null, SR.GetString(SR.ID8025));
133 // Complete asynchronously
138 if (resetEvent != null)
144 // finally call the call back. Note, we are expecting user's callback to handle the exception
145 // so, if the callback throw exception, all we can do is burn and crash.
149 if (callback != null)
152 catch (ThreadAbortException)
155 // The thread running the callback is being aborted. We ignore this case.
158 catch (AsynchronousOperationException)
162 #pragma warning suppress 56500
163 catch (Exception unhandledException)
166 // The callback raising an exception is equivalent to Main raising an exception w/out a catch.
167 // We should just throw it back. We should log the exception somewhere.
169 // Because the stack trace gets lost on a rethrow, we're wrapping it in a generic exception
170 // so the stack trace is preserved.
172 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AsynchronousOperationException(SR.GetString(SR.ID4003), unhandledException));
177 /// Disposes of unmanaged resources held by the AsyncResult.
179 /// <param name="isExplicitDispose">True if this is an explicit call to Dispose.</param>
180 protected virtual void Dispose(bool isExplicitDispose)
184 if (isExplicitDispose)
196 // Called explicitly to close the object
198 if (resetEvent != null)
206 // Called for finalization
212 #region IAsyncResult implementation
215 /// Gets the user-defined state information that was passed to the Begin method.
217 public object AsyncState
226 /// Gets the wait handle of the async event.
228 public virtual WaitHandle AsyncWaitHandle
232 if (resetEvent == null)
234 bool savedCompleted = completed;
238 if (resetEvent == null)
239 resetEvent = new ManualResetEvent(completed);
242 if (!savedCompleted && completed)
251 /// Gets a value that indicates whether the asynchronous operation completed synchronously.
253 public bool CompletedSynchronously
257 return completedSync;
262 /// Gets a value that indicates whether the asynchronous operation has completed.
264 public bool IsCompleted
274 #region IDisposable Members
277 /// Disposes this object
279 public void Dispose()
283 GC.SuppressFinalize(this);