我有一个异步方法
public Task<Car> GetCar()
{
}
我可以使用async和await调用这个方法:
Car car = await GetCar()
如何使用 MethodInfo.Invoke 调用方法并异步等待结果。
MethodInfo method = obj.GetMethod("GetCar");
method.Invoke( obj, null)
我有一个异步方法
public Task<Car> GetCar()
{
}
我可以使用async和await调用这个方法:
Car car = await GetCar()
如何使用 MethodInfo.Invoke 调用方法并异步等待结果。
MethodInfo method = obj.GetMethod("GetCar");
method.Invoke( obj, null)
您可以正常调用它,然后await
返回的任务:
Task<Car> result = (Task<Car>)method.Invoke(obj, null);
await result;
await
不会阻塞当前线程。这正是 await
的全部意义所在。它真正是非阻塞的。我有一篇异步简介和另一篇博客文章,其中更详细地介绍了这个概念。 - Stephen Clearyasync
视为将方法转换成状态机,而每个await
是状态机方法返回的(潜在)点。从这个角度来看,await
只是一种非常复杂的回调语法。因此,虽然await
确实会“暂停”方法直到可等待操作完成并将局部变量提升到堆上,但重要的是要注意:1)没有线程等待方法继续执行(它是回调而不是线程),2)调用栈不会被保留(回调直接执行状态机的下一部分)。 - Stephen Clearyawait
使用回调函数。当操作完成时,回调函数就是方法的继续执行。async
关键字告诉编译器将方法分成块(在每个await
点),然后当await
暂停时,它只需将下一个方法块连接为回调函数。因此,这些都没有监视器、代理或管理器;一切都是回调函数。这也是为什么调用堆栈会丢失的原因;该块直接作为回调函数运行,而没有原始调用堆栈。 - Stephen Cleary
TaskCompletionSource<TResult>
来实现这一点,但是我需要知道如何从MethodInfo.Invoke
中获取结果。 如果我尝试等待TaskCompletionSource.Task
,我会得到一个System.ArgumentException
,其中提供了以下消息:“ 无法将返回类型为“System.Threading.Tasks.Task`1 [TResult]”的对象转换为类型“System.Threading.Tasks.Task”。” 这是我的代码:private async Task AsyncMethod()
{
await Task.Delay(1000);
return 42;
}
private async Task InvokeAsyncMethod()
{
var method = GetType().GetTypeInfo().GetDeclaredMethod(nameof(AsyncMethod));
var tcs = new TaskCompletionSource();
var task = (Task)tcs.Task; // Throws ArgumentException
method.Invoke(this, null);
return await task;
}
- Markus Palme