1
// Copyright 2004-2008 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.Facilities
.Synchronize
18 using System
.Threading
;
21 /// Abstract result for asynchronous operations.
23 public abstract class AbstractAsyncResult
: IAsyncResult
26 private int completed
;
27 private int invokedCallback
;
28 private readonly object asyncState
;
29 private readonly AsyncCallback _asyncCallback
;
30 private bool completedSynchronously
;
31 private bool endCalled
;
32 private Exception exception
;
33 private object result
;
34 private object waitEvent
;
37 /// Initializes a new <see cref="AbstractAsyncResult"/>
39 /// <param name="callback">The async callback.</param>
40 /// <param name="state">The async state</param>
41 protected AbstractAsyncResult(AsyncCallback callback
, object state
)
44 _asyncCallback
= callback
;
45 invokedCallback
= (callback
!= null) ? 0 : 1;
48 #region IAsyncResult Members
51 /// Gets the asynchournous state.
53 public object AsyncState
55 get { return asyncState; }
59 /// Determines if the result is available.
61 public bool IsCompleted
63 get { return (completed != 0); }
67 /// Determines if the result completed synchronously.
69 public bool CompletedSynchronously
71 get { return completedSynchronously; }
72 protected internal set
74 completedSynchronously
= value;
79 /// Gets the asynchronous <see cref="WaitHandle"/>.
81 public WaitHandle AsyncWaitHandle
85 int isCompleted
= completed
;
87 if (waitEvent
== null)
89 Interlocked
.CompareExchange(ref waitEvent
,
90 new ManualResetEvent(isCompleted
!= 0), (object)null);
93 ManualResetEvent ev
= (ManualResetEvent
)waitEvent
;
95 if ((isCompleted
== 0) && (completed
!= 0))
105 /// Ends the asynchronous request.
107 /// <param name="asyncResult">The asynchronous result.</param>
108 /// <returns>The result.</returns>
109 public static object End(IAsyncResult asyncResult
)
111 if (asyncResult
== null)
113 throw new ArgumentNullException("asyncResult");
116 AbstractAsyncResult result
= asyncResult
as AbstractAsyncResult
;
120 throw new ArgumentException("Unrecognized IAsyncResult", "result");
123 if (result
.endCalled
)
125 throw new InvalidOperationException("IAsyncResult has already ended");
128 result
.endCalled
= true;
130 if (result
.completed
== 0)
132 result
.AsyncWaitHandle
.WaitOne();
135 if (result
.exception
!= null)
137 throw result
.exception
;
140 return result
.result
;
146 /// Completes the asynchronous request.
148 /// <param name="synchronously">true if synchronously.</param>
149 protected void Complete(bool synchronously
)
151 completedSynchronously
= synchronously
;
153 Interlocked
.Increment(ref completed
);
155 if (waitEvent
!= null)
157 ((ManualResetEvent
)waitEvent
).Set();
160 if ((_asyncCallback
!= null) && (Interlocked
.Increment(ref invokedCallback
) == 1))
162 _asyncCallback(this);
169 /// Completes the asynchronous request.
171 /// <param name="synchronously">true if synchronously.</param>
172 /// <param name="result">The result.</param>
173 protected void Complete(bool synchronously
, object result
)
175 this.result
= result
;
176 Complete(synchronously
);
180 /// Completes the asynchronous request with exception.
182 /// <param name="synchronously">true if synchronously.</param>
183 /// <param name="exception">The exception.</param>
184 protected void Complete(bool synchronously
, Exception exception
)
186 this.exception
= exception
;
187 Complete(synchronously
);
191 /// Performs any cleanup.
193 protected virtual void Cleanup()
197 private void InternalCleanup()
199 if (Interlocked
.Increment(ref cleanUp
) == 1)
206 /// Finalizer to ensure cleanup.
208 ~
AbstractAsyncResult()