Reputation: 1085
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();
}
Upvotes: 5
Views: 3326
Reputation: 136697
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.
Upvotes: 5
Reputation: 1063338
I find the whole Begin/End pattern unnecessarily complex - so I had a look at wrapping it up (very comparable to what F# uses). Result: no more need to keep the delegate (etc).
Upvotes: 2
Reputation: 29575
Try passing the delegate as the async state parameter such as,
class Program {
static void Main(string[] args) {
Action d = delegate {
Console.WriteLine("From the delegate");
};
var e = new ManualResetEvent(false);
d.BeginInvoke(r => {
((Action)r.AsyncState).EndInvoke(r);
e.Set();
}, d);
e.WaitOne();
}
}
Upvotes: 0
Reputation: 755131
IAsyncResult is a very ... overused interface. To be a usable interface in so many scenarios it can only really have the properties and fields which are applicable to all scenarios in which it is used. Otherwise APIs would be struggling to provide parameters which were simply not natural to their specific needs.
In only a subset of the circumstances is the creation of a IAsyncResult occur for a delegate. Other scenarios like Control.BeginInvoke do not begin with a delegate and would not be able to supply one to the interface properties if they existed.
IAsyncResult takes the minimalist approach here and has only the properties all uses of it can supply.
Upvotes: 1