与Casting TResult in Task<TResult> to System.Object相关。我正在为服务构建一个通用的异步命令执行函数。
执行通用命令的方法如下所示:
public async Task<object> ExecuteCommandAsync(string cmdName, CommandData data)
代码使用反射来查找具有给定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); });
我担心这样做会否定异步的价值:获得结果现在是一个阻塞调用,所以我不妨使用同步方法。
答案 0 :(得分:5)
您可以等待任务,然后在完成后反映结果
public static async Task<object> AwaitResult(Task t)
{
await t;
return t.GetType().GetProperty("Result").GetValue(t, null);
}
或者:
return ((dynamic)t).Result;
答案 1 :(得分: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;
}
特别是,我建议不要使用Task.Run
因为这会浪费一个帖子,我不建议使用Task.Result
,因为它会封装AggregateException
内的所有异常1}}。