当使用 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);
}
这非常有效,因为它知道委托(delegate)的类型是什么,因此可以对其进行转换。然而,当您有两个 Put
方法时,它开始变得困惑,因为尽管该方法返回 void,您似乎必须将其转换为强类型委托(delegate)以结束调用,例如
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");
}
我希望有一种更简洁的方法来执行此操作,因为我唯一关心委托(delegate)的是返回类型(在本例中为 void),而不是提供给它的参数。但是我在办公室里绞尽脑汁问过其他人,也没有人想出答案。
我知道一个解决方案是编写一个自定义的 IAsyncResult
,但这是一项非常困难的任务,因为围绕诸如 WaitHandle
的惰性实例化之类的问题存在潜在的线程问题,我我宁愿使用这种看起来有点怪异的代码也不愿走那条路。
关于如何在没有层叠的 is
检查集的情况下结束调用的任何想法?
最佳答案
我错了,有更简洁的方法。
您在已经知道委托(delegate)的特定类型的同一上下文中为特定的 EndInvoke()
方法创建 Action( IAsyncResult )
委托(delegate),将其作为异步状态。为了方便起见,我将 EndPut()
作为回调传递。
IAsyncResult BeginPut( string key, object value ) {
Action<string, object> put = this.Put;
return put.BeginInvoke( key, value, EndPut,
new Action<IAsyncResult>( put.EndInvoke ) );
}
IAsyncResult BeginPut( string region, string key, object value ) {
Action<string, string, object> put = this.Put;
return put.BeginInvoke( region, key, value, EndPut,
new Action<IAsyncResult>( put.EndInvoke ) );
}
然后你完成它。
void EndPut( IAsyncResult asyncResult ) {
var del = asyncResult.AsyncState as Action<IAsyncResult>;
del( asyncResult );
}
关于c# - 使用部分类型信息结束异步委托(delegate)调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/189228/