When writing async method implementations using the BeginInvoke/EndInvoke pattern the code might look something like the following (and to save you guessing this is an async wrapper around a cache):
IAsyncResult BeginPut(string key, object value)
{
Action<string, object> put = this.cache.Put;
return put.BeginInvoke(key, value, null, null);
}
void EndPut(IAsyncResult asyncResult)
{
var put = (Action<string, object>)((AsyncResult)asyncResult).AsyncDelegate;
put.EndInvoke(asyncResult);
}
This works perfectly well because it's known what the type of delegate is, so it can be cast. However it starts to get messy when you have two Put
methods, because although the method returns void you seemingly have to cast it to a strongly typed delegate to end the invocation, e.g.
IAsyncResult BeginPut(string key, object value)
{
Action<string, object> put = this.cache.Put;
return put.BeginInvoke(key, value, null, null);
}
IAsyncResult BeginPut(string region, string key, object value)
{
Action<string, string, object> put = this.cache.Put;
return put.BeginInvoke(region, key, value, null, null);
}
void EndPut(IAsyncResult asyncResult)
{
var put = ((AsyncResult)asyncResult).AsyncDelegate;
var put1 = put as Action<string, object>;
if (put1 != null)
{
put1.EndInvoke(asyncResult);
return;
}
var put2 = put as Action<string, string, object>;
if (put2 != null)
{
put2.EndInvoke(asyncResult);
return;
}
throw new ArgumentException("Invalid async result", "asyncResult");
}
I'm hoping there is a cleaner way to do this, because the only thing I care about the delegate is the return type (in this case void) and not the arguments that were supplied to it. But I've racked my brains and asked others in the office, and nobody can think of the answer.
I know one solution is to write a custom IAsyncResult
, but that's such a difficult task with the potential threading issues around things like lazy instantiation of the WaitHandle
that I'd rather have this slightly hacky looking code than go down that route.
Any ideas on how to end the invocation without a cascading set of is
checks?