Why does IAsyncResult
require I keep a reference to the Delegate that BeginInvoked
it?
I would like to be able to write something like:
new GenericDelegate(DoSomething).BeginInvoke(DoSomethingComplete);
void DoSomethingComplete(IAsyncResult ar)
{
ar.EndInvoke();
}
The IAsyncResult interface is implemented by classes containing methods that can operate asynchronously. It is the return type of methods that initiate an asynchronous operation, such as FileStream. BeginRead, and it is passed to methods that conclude an asynchronous operation, such as FileStream.
The AsyncCallback delegate represents a callback method that is called when the asynchronous operation completes. The callback method takes an IAsyncResult parameter, which is subsequently used to obtain the results of the asynchronous operation.
You don't need to keep your own reference to a delegate when doing a normal1 delegate BeginInvoke
; you can cast the IAsyncResult
to an AsyncResult
and retrieve the delegate from the AsyncDelegate
property. And before anybody says "that's a dirty hack", it's documented as being valid at MSDN.
The AsyncResult class is used in conjunction with asynchronous method calls made using delegates. The IAsyncResult returned from the delegate's BeginInvoke method can be cast to an AsyncResult. The AsyncResult has the AsyncDelegate property that holds the delegate object on which the asynchronous call was invoked.
So you could write:
new GenericDelegate(DoSomething).BeginInvoke(DoSomethingComplete);
void DoSomethingComplete(IAsyncResult ar)
{
((GenericDelegate)((AsyncResult)ar).AsyncDelegate)).EndInvoke();
}
Note that you do still have to know the type of the original delegate (or at least, I haven't found a way around this limitation; then again I haven't tried).
1 By "normal" here I mean a BeginInvoke
on a delegate instance, using the compiler-generated method. This technique of casting to AsyncResult
is not guaranteed to work when using pre-defined methods, i.e. when using a class which declares its own BeginX/EndX
methods. This is because the class may be doing something more clever internally such as blocking on IO completion ports, and may therefore use a different type of IAsyncResult
. However, in the scenario as posited, it will work just fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With