如何通过C#中的Task调用反射方法?

时间:2018-04-30 15:35:30

标签: c# task-parallel-library

我有一些使用Reflection运行某些方法的C#代码。该代码如下所示:

MyClass myClass = InitializeMyClass();

string[] methods = GetMethodsToRun();
foreach (var method in methods)
{
  MethodInfo m = myClass.GetType().GetMethod(method);
  m.Invoke(myClass, null);  
}

此代码有效。但是,我需要并行运行这些方法。出于这个原因,我一直在看任务并行库。为了通过任务并行库并行运行方法,我需要为每个方法创建Task个实例。为了做到这一点,我已将上面的代码更新为:

MyClass myClass = InitializeMyClass();

string[] methods = GetMethodsToRun();
foreach (var method in methods)
{
  MethodInfo m = myClass.GetType().GetMethod(method);
  Task<object> task = Task.Run<object>(method.Invoke(myClass, null));
}

但是,这不起作用,因为method.Inkove返回object。我想通过使用.Run<object>来传达我想要运行的代码的返回类型。不过,我收到一个编译时错误,上面写着:

参数1:无法从'object'转换为'System.Func'

突然之间,我觉得我这太难了。我的问题是,如何通过C#调用反射方法作为任务?

谢谢

3 个答案:

答案 0 :(得分:1)

以下是您正在使用的方法的签名:

public static Task<TResult> Run<TResult>(Func<TResult> function);

如果您注意到,泛型类型是结果的类型,而调用的参数是返回结果的函数。

因此,根据您的代码,您需要一个返回类型object的函数:

Task<object> task = Task.Run<object>(
     () => 
     { 
         return m.Invoke(myClass, null); //returns object
     });

然后您可以继续使用结果:

 task.ContinueWith(
    (o) => 
    {
        Console.WriteLine(o.Result); //Result contains the actual result of the method call.
    });

在这两种情况下,我们都使用lambda表达式定义了匿名函数。它不一定是这样。您也可以提供自己的功能:

task.ContinueWith(WriteObject);

private void WriteObject(Task<object> o)
{
    Console.WriteLine(o.Result);
}

答案 1 :(得分:0)

Task.Run()需要System.Func<TResult>(或System.Action)delecate。

您的代码立即调用该函数,然后将其结果(不是委托)传递给Task.Run()。那不会起作用。

相反,您需要调用Delegate.CreateDelegate()来创建一个指向MethodInfo(使用您的实例)的正确类型的委托(这将取决于方法的返回类型),强制转换到Func<T>Action,然后将其传递给Task.Run()

答案 2 :(得分:0)

MyClass myClass = InitializeMyClass();

string[] methods = GetMethodsToRun();
foreach (var method in methods)
{
  MethodInfo m = myClass.GetType().GetMethod(method);
  Task.Run(() =>  m.Invoke(myClass, null));
}