通常调用Task <T>方法

Qua*_*ngo 4 c# generics task async-await

任务<TResult>中的Castes TResult到System.Object相关.我正在为服务构建一个通用的异步命令执行函数.

执行通用命令的方法如下所示:

public async Task<object> ExecuteCommandAsync(string cmdName, CommandData data)
Run Code Online (Sandbox Code Playgroud)

代码使用反射来查找具有给定的类的方法cmdName.调用它将返回Type<T>- 我们T事先不知道.然而,由于Task<T>不是协变,我不能投Task<object>.

目前我的解决方案(根据21805564)是调用Result方法并封装在一个Task.Run,如下所示:

// find the method
MethodInfo cmd = GetMethod(cmdName);
var task = (Task)cmd.Invoke(this, data);
return await Task.Run<object>(() => { return task.GetType().GetProperty("Result").GetValue(task); });
Run Code Online (Sandbox Code Playgroud)

我担心的是,这样做会否定异步的价值:获得结果现在是一个阻塞调用,所以我不妨使用同步方法.

Lee*_*Lee 5

您可以等待任务,然后在完成后反映结果

public static async Task<object> AwaitResult(Task t)
{
    await t;
    return t.GetType().GetProperty("Result").GetValue(t, null);
} 
Run Code Online (Sandbox Code Playgroud)

要么:

return ((dynamic)t).Result;
Run Code Online (Sandbox Code Playgroud)


Ste*_*ary 5

请记住,这dynamic是可用的.只要你不使用,你可以做这样的事情Microsoft.Bcl.Async:

public async Task<dynamic> ExecuteCommandAsync(string cmdName, CommandData data)
{
  MethodInfo cmd = GetMethod(cmdName);
  dynamic task = cmd.Invoke(this, data);
  return await task;
}
Run Code Online (Sandbox Code Playgroud)

特别是,我不推荐使用,Task.Run因为这会浪费一个线程,我不建议使用Task.Result因为它将封装任何异常AggregateException.