我最近第一次使用异步(和真正的.Net 4.5),我遇到了一些让我难过的事情。我在网上找不到太多关于这VoidTaskResult
门课的信息,所以我来这里看看是否有人对正在发生的事情有任何想法。
我的代码如下所示。显然,这被简化了很多。基本思想是调用插件方法,它们是异步的。如果它们返回Task
,则异步调用没有返回值。如果他们回来Task<>
了,那就有。我们事先不知道它们是哪种类型,所以想法是使用反射查看结果的类型(IsGenericType
如果类型是则为真Type<>
)并使用动态类型获取值。
在我的真实代码中,我通过反射调用插件方法。我认为这不会对我所看到的行为产生影响。
// plugin method
public Task yada()
{
// stuff
}
public async void doYada()
{
Task task = yada();
await task;
if (task.GetType().IsGenericType)
{
dynamic dynTask = task;
object result = dynTask.Result;
// do something with result
}
}
这适用于上面显示的插件方法。IsGenericType
是假的(如预期的那样)。
但是,如果您稍微更改插件方法的声明,IsGenericType
现在返回 true 并且内容会中断:
public async Task yada()
{
// stuff
}
执行此操作时,将在行上引发以下异常object result = dynTask.Result;
:
如果您深入研究任务对象,它实际上似乎是Type<VoidTaskResult>
. VoidTaskResult
是 Threading 命名空间中的私有类型,其中几乎没有任何内容。
我尝试更改调用代码:
public async void doYada()
{
Task task = yada();
await task;
if (task.GetType().IsGenericType)
{
object result = task.GetType().GetProperty("Result").GetMethod.Invoke(task, new object[] { });
// do something with result
}
}
从它不再抛出的意义上说,这“成功”了,但现在结果是VoidTaskResult
我无法明智地做任何事情的类型。
我应该补充一点,我什至很难为这一切制定一个真正的问题。也许我真正的问题是“什么是VoidTaskResult
?”,或者“为什么当我动态调用异步方法时会发生这种奇怪的事情?” 甚至可能是“你如何调用可选异步的插件方法?” 无论如何,我把它放在那里是希望其中一位大师能够阐明一些观点。