如何通过 C# 中的任务调用反射方法?
How to invoke reflected method via a Task in C#?
我有一些 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 return 是 object
。我想通过使用 .Run<object>
传达我想要 运行 的 return 类型的代码。尽管如此,我还是收到一个编译时错误:
参数 1:无法从 'object' 转换为 'System.Func'
突然间,我觉得我把这件事搞得太难了。我的问题是,如何通过 C# 将反射方法作为任务调用?
谢谢
Task.Run()
接受 System.Func<TResult>
(或 System.Action
)委托。
您的代码立即调用该函数,然后将其结果(不是委托)传递给 Task.Run()
。那不行。
相反,您需要调用 Delegate.CreateDelegate()
来创建指向 MethodInfo
(使用您的实例),将其转换为 Func<T>
或 Action
,然后将其传递给 Task.Run()
.
MyClass myClass = InitializeMyClass();
string[] methods = GetMethodsToRun();
foreach (var method in methods)
{
MethodInfo m = myClass.GetType().GetMethod(method);
Task.Run(() => m.Invoke(myClass, null));
}
这是您正在使用的方法的签名:
public static Task<TResult> Run<TResult>(Func<TResult> function);
如果您注意到,泛型类型是结果的类型,而调用的参数是 returns 结果的函数。
因此,根据您的代码,您需要一个 returns 类型 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);
}
我有一些 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 return 是 object
。我想通过使用 .Run<object>
传达我想要 运行 的 return 类型的代码。尽管如此,我还是收到一个编译时错误:
参数 1:无法从 'object' 转换为 'System.Func'
突然间,我觉得我把这件事搞得太难了。我的问题是,如何通过 C# 将反射方法作为任务调用?
谢谢
Task.Run()
接受 System.Func<TResult>
(或 System.Action
)委托。
您的代码立即调用该函数,然后将其结果(不是委托)传递给 Task.Run()
。那不行。
相反,您需要调用 Delegate.CreateDelegate()
来创建指向 MethodInfo
(使用您的实例),将其转换为 Func<T>
或 Action
,然后将其传递给 Task.Run()
.
MyClass myClass = InitializeMyClass();
string[] methods = GetMethodsToRun();
foreach (var method in methods)
{
MethodInfo m = myClass.GetType().GetMethod(method);
Task.Run(() => m.Invoke(myClass, null));
}
这是您正在使用的方法的签名:
public static Task<TResult> Run<TResult>(Func<TResult> function);
如果您注意到,泛型类型是结果的类型,而调用的参数是 returns 结果的函数。
因此,根据您的代码,您需要一个 returns 类型 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);
}