c# 在回调中调用 endinvoke,使用泛型

标签 c# generics asynchronous c#-2.0

BeginInvoke 之后的回调中,AsyncResult.AsyncDelegate 需要转换为正确的类型,然后才能访问 EndInvoke

但是我正在使用泛型,那么我是否需要为 N 个泛化方法定义 N 个回调?

这是类:

public class Async
    {
        public delegate object Func(); //void with no parameter
        public delegate TResult Func<T, TResult>(T arg); //one parameter with result

        public static void Execute(IAsyncSubscriber subscriber, Func action)
        {
            action.BeginInvoke(Callback, subscriber);
        }

        public static void Execute<T, T1>(IAsyncSubscriber subscriber, T param, Func<T, T1> action)
        {
            action.BeginInvoke(param, Callback, subscriber);
        }

        private static void Callback(IAsyncResult ar)
        {
            AsyncResult result = (AsyncResult)ar;
            IAsyncSubscriber subscriber = (IAsyncSubscriber)result.AsyncState;
            Func action = (Func) result.AsyncDelegate;
            object returnValue = action.EndInvoke(result); //To call endinvoke 
            subscriber.Callback(returnValue);
        }
    }

最佳答案

有几种方法可以避免定义 N 个回调:

  1. 您可以在 BeginInvoke 调用中将相应的 EndInvoke 方法作为状态传递。例如

    private delegate T EndInvokeDelegate<T>(IAsyncResult ar);
    
    public static void Execute<T, T1>(IAsyncSubscriber subscriber, T param, Func<T, T1> action)
    {
        action.BeginInvoke(param, Callback<T1>, new object[]{subscriber, new new EndInvokeDelegate<T1>(action.EndInvoke)});
    }
    
    public static void Execute<T, T1, T2>(IAsyncSubscriber subscriber, T param1, T1 param2, Func<T, T1, T2> action)
    {
        action.BeginInvoke(param1, param2, Callback<T2>, new object[]{subscriber, new new EndInvokeDelegate<T2>(action.EndInvoke)});
    }
    
    private static void Callback<TR>(IAsyncResult ar)
    {
        object[] stateArr = (object[])ar.AsyncState;
        IAsyncSubscriber subscriber = (IAsyncSubscriber)stateArr[0];
        EndInvokeDelegate<TR> action = (EndInvokeDelegate<TR>)stateArray[1];
        TR returnValue = action(ar);
        subscriber.Callback(returnValue);
    }     
    

    您还可以通过将 stateArray[1] 视为 MultiCastDelegate 并在其上使用 DynamicInvoke 来使 Callback 成为非泛型,但这会很慢。

  2. 对于 .Net 2.0 和 3.0,您可以使用反射,例如

    Type actionType= result.AsyncDelegate.GetType();
    var minfo = actionType.GetMethod("EndInvoke");
    object returnValue = minfo.Invoke(res.AsyncDelegate, new object[] { ar });
    
  3. 对于 .Net 4.0,您可以使用动态。例如

    dynamic action = result.AsyncDelegate; 
    object returnValue = action.EndInvoke(result);
    

关于c# 在回调中调用 endinvoke,使用泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11392978/

相关文章:

c# - WPF 中的编号列表

arrays - 嵌套在 async.eachSeries 循环中的 async.series 终止提前发送 POST 响应

c# - 以编程方式将图像附加到椭圆

c# - 使用 xampp 的 C# 中的 MySql 错误 1064

swift - 基于字符串的枚举是否有 Swift 类型?

c# - 作为一名熟练的 c# 程序员,Java 类型参数推理规则中有哪些陷阱在等着我?

java 类型删除与 Field#getGenericType 和 Method#getGenericReturnType

javascript - Nodejs 异步循环正在阻止 React UI 渲染

node.js - 在 Node.js 中,我如何使用集合作为索引以编程方式从 Redis 数据库中检索许多哈希

c# - c# 的角色/权限框架?