【问题标题】:Asynchronous runtime method invocation异步运行时方法调用
【发布时间】:2009-11-04 19:35:31
【问题描述】:

我在运行时加载一些程序集并使用反射 (MethodInfo.Invoke) 在它们上调用方法。

现在我想让这些调用异步。所以我正在考虑使用 Delegate.BeginInvoke()。但我不确定如何通过在运行时提供函数名称来创建委托实例。 (我看到的所有示例都在编译时解析了委托实例目标。)我有一个 MethodInfo 对象,其中包含要调用的方法。有没有办法做到这一点?

   public void Invocation(Object[] inputObjs)
    {
        public delegate string DelegateMethodInfo(int num);

        Assembly assm = Assembly.Load(assemblyName);
        Type type = assm.GetType(className);
        Type[] ctorParams = new Type[0];
        Object[] objs = new Object[0];

        ConstructorInfo ctorInf = type.GetConstructor(ctorParams);
        Object classObj = ctorInf.Invoke(objs);
        MethodInfo methodInf = type.GetMethod(methodName);

        // Need asynchronous invocation.
        //Object retObj = methodInf.Invoke(classObj, inputObjs);

        DelegateMethodInfo del = new DelegateMethodInfo(???); // How to instantiate the delegate???
        del.BeginInvoke((int)inputObjs[0], null, null);
    }

【问题讨论】:

    标签: c# reflection delegates invoke methodinfo


    【解决方案1】:

    您可以使用Delegate.CreateDelegate - 但您需要知道签名,以便创建合适类型的委托。当您基本上只获得 MethodInfo 时,这有点棘手:( 更糟糕的是,没有等效的 Delegate.DynamicInvoke 用于异步执行。

    说实话,最简单的事情是启动一个调用该方法的新线程池作业:

    ThreadPool.QueueUserWorkItem(delegate { methodInf.Invoke(classObj, inputObjs);});
    

    【讨论】:

    • 是否可以准确地说在 Delegate.CreateDelegate 上使用 ThreadPool.QueueUserWorkItem 是“将异步执行移到调用堆栈中更高的位置”?无论如何,这对我来说似乎是一种更好的方法。
    • 这是一个相当合理的描述,是的。
    【解决方案2】:

    只需使用包装对 methodInf.Invoke 的调用的 lambda 表达式。生成的委托类型为DelegateMethodInfo

    【讨论】:

      【解决方案3】:

      这与其他答案类似,但您可以创建一个新的 Func 并将 methodInf.Invoke 方法分配给它。这是一个例子

      class Other
      {
          public void Stuff()
          { Console.WriteLine("stuff"); }
      }
      
      static void Main(string[] args)
      {
          var constructor = typeof(Other).GetConstructor(new Type[0]);
          var obj = constructor.Invoke(null);
      
          var method = typeof(Other).GetMethods().First();
          Func<object, object[], object> delegate = method.Invoke;
          delegate.BeginInvoke(obj, null, null, null);
      
          Console.ReadLine();
      }
      

      它所做的是创建一个Func&lt;object, object[], object&gt; 类型的新变量,它与MethodInfo.Invoke 的签名相匹配。然后它获取对对象上实际调用方法的引用,并将该引用粘贴到变量中。

      因为Func&lt;&gt;是一个委托类型,那么你可以使用BeginInvoke

      【讨论】:

        【解决方案4】:

        您是否考虑过使用 MethodInvoker(委托,而不是类)而不是尝试创建额外的委托?通过使用匿名方法,您可以完成您需要的内容。或者我可能正在吸烟。但是,基本上,MethodInvoker 充当标准的无参数委托,然后在 anon 方法中,您将参数传递给 MethodInvoker 的匿名代码。我已经在 WinForms 中使用它来执行 Form.BeginInvoke 而无需左右创建委托。如果需要,您可以等待,回复我,我今晚会给您提供示例代码(我在美国西海岸... GMT -8)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多