1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2003-2005 Microsoft Corporation, All rights reserved.
3 // ----------------------------------------------------------------------------
6 using System
.Diagnostics
;
7 using System
.Threading
;
9 namespace Microsoft
.ServiceModel
.Samples
12 /// A generic base class for IAsyncResult implementations
13 /// that wraps a ManualResetEvent.
15 abstract class AsyncResult
: IAsyncResult
17 AsyncCallback callback
;
19 bool completedSynchronously
;
23 ManualResetEvent manualResetEvent
;
26 protected AsyncResult(AsyncCallback callback
, object state
)
28 this.callback
= callback
;
30 this.thisLock
= new object();
33 public object AsyncState
41 public WaitHandle AsyncWaitHandle
45 if (manualResetEvent
!= null)
47 return manualResetEvent
;
52 if (manualResetEvent
== null)
54 manualResetEvent
= new ManualResetEvent(isCompleted
);
58 return manualResetEvent
;
62 public bool CompletedSynchronously
66 return completedSynchronously
;
70 public bool IsCompleted
86 // Call this version of complete when your asynchronous operation is complete. This will update the state
87 // of the operation and notify the callback.
88 protected void Complete(bool completedSynchronously
)
92 // It is a bug to call Complete twice.
93 throw new InvalidOperationException("Cannot call Complete twice");
96 this.completedSynchronously
= completedSynchronously
;
98 if (completedSynchronously
)
100 // If we completedSynchronously, then there is no chance that the manualResetEvent was created so
101 // we do not need to worry about a race condition.
102 Debug
.Assert(this.manualResetEvent
== null, "No ManualResetEvent should be created for a synchronous AsyncResult.");
103 this.isCompleted
= true;
109 this.isCompleted
= true;
110 if (this.manualResetEvent
!= null)
112 this.manualResetEvent
.Set();
117 // If the callback throws, there is a bug in the callback implementation
118 if (callback
!= null)
124 // Call this version of complete if you raise an exception during processing. In addition to notifying
125 // the callback, it will capture the exception and store it to be thrown during AsyncResult.End.
126 protected void Complete(bool completedSynchronously
, Exception exception
)
128 this.exception
= exception
;
129 Complete(completedSynchronously
);
132 // End should be called when the End function for the asynchronous operation is complete. It
133 // ensures the asynchronous operation is complete, and does some common validation.
134 protected static TAsyncResult End
<TAsyncResult
>(IAsyncResult result
)
135 where TAsyncResult
: AsyncResult
139 throw new ArgumentNullException("result");
142 TAsyncResult asyncResult
= result
as TAsyncResult
;
144 if (asyncResult
== null)
146 throw new ArgumentException("Invalid async result.", "result");
149 if (asyncResult
.endCalled
)
151 throw new InvalidOperationException("Async object already ended.");
154 asyncResult
.endCalled
= true;
156 if (!asyncResult
.isCompleted
)
158 asyncResult
.AsyncWaitHandle
.WaitOne();
161 if (asyncResult
.manualResetEvent
!= null)
163 asyncResult
.manualResetEvent
.Close();
166 if (asyncResult
.exception
!= null)
168 throw asyncResult
.exception
;
175 //An AsyncResult that completes as soon as it is instantiated.
176 class CompletedAsyncResult
: AsyncResult
178 public CompletedAsyncResult(AsyncCallback callback
, object state
)
179 : base(callback
, state
)
184 public static void End(IAsyncResult result
)
186 AsyncResult
.End
<CompletedAsyncResult
>(result
);
190 //A strongly typed AsyncResult
191 abstract class TypedAsyncResult
<T
> : AsyncResult
195 protected TypedAsyncResult(AsyncCallback callback
, object state
)
196 : base(callback
, state
)
205 protected void Complete(T data
, bool completedSynchronously
)
208 Complete(completedSynchronously
);
211 public static T
End(IAsyncResult result
)
213 TypedAsyncResult
<T
> typedResult
= AsyncResult
.End
<TypedAsyncResult
<T
>>(result
);
214 return typedResult
.Data
;
218 //A strongly typed AsyncResult that completes as soon as it is instantiated.
219 class TypedCompletedAsyncResult
<T
> : TypedAsyncResult
<T
>
221 public TypedCompletedAsyncResult(T data
, AsyncCallback callback
, object state
)
222 : base(callback
, state
)
224 Complete(data
, true);
227 public new static T
End(IAsyncResult result
)
229 TypedCompletedAsyncResult
<T
> completedResult
= result
as TypedCompletedAsyncResult
<T
>;
230 if (completedResult
== null)
232 throw new ArgumentException("Invalid async result.", "result");
235 return TypedAsyncResult
<T
>.End(completedResult
);