当使用 BeginInvoke/EndInvoke 模式编写异步方法实现时,代码可能如下所示(为了避免您猜测这是一个围绕缓存的异步包装器):
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);
}
这非常有效,因为它知道委托的类型是什么,因此可以强制转换。但是,当您有两个方法时,它开始变得混乱Put
,因为尽管该方法返回 void 您似乎必须将其强制转换为强类型委托以结束调用,例如
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");
}
我希望有一种更简洁的方法来做到这一点,因为我唯一关心委托的是返回类型(在本例中为 void),而不是提供给它的参数。但我绞尽脑汁问办公室里的其他人,谁也想不出答案。
我知道一个解决方案是编写一个 custom IAsyncResult
,但这是一项艰巨的任务,因为潜在的线程问题围绕着诸如延迟实例化之类的事情WaitHandle
,我宁愿拥有这个看起来有点 hacky 的代码而不是沿着这条路线走。
关于如何在没有级联is
检查的情况下结束调用的任何想法?