c# - 使用部分类型信息结束异步委托(delegate)调用

标签 c# asynchronous delegates

当使用 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/

相关文章:

C# 将字符串 [] 数组与通用对象列表进行比较

javascript - 如何从异步调用返回响应?

c# - 所有方法的委托(delegate)

c# - asp.net:如何将类似 LinkBut​​ton 的链接功能与表格单元格背景上的委托(delegate)连接起来?

c# - 在桌面应用程序中管理 session 的 Ninject 范围

c# - 无法使用 Linq 插入到 SQL Server Always Encrypted 表中

c# - 从 Task<T> 中检索 T

asynchronous - Cassandra 异步写入

ios - 第一个 View 中的委托(delegate)方法不会从第二个 View 中调用

C# - 数组转置位级别