(问题的真正标题应该是“为什么我会收到‘无法将类型为‘System.Runtime.CompilerServices.TaskAwaiter`1[System.Runtime.CompilerServices.VoidTaskResult]’的对象转换为‘System.Runtime. CompilerServices.INotifyCompletion'”,但不幸的是这对于 StackOverflow 来说太长了。:)
嗨,
在尝试
await
执行我的方法时遇到了非常奇怪的问题。调用代码如下所示(摘录):
private async Task DownloadAddonFileAsync(dynamic addon, dynamic file, string targetFolder)
{
// ...
await DownloadFileAsync(file, targetFolder, uri);
DownloadFileAsync 看起来像这样:
protected async Task DownloadFileAsync(dynamic file, string targetFolder, string uri)
{
// ...
var fileBytes = await AppLoaderRestClient.GetAsync<byte[]>(uri);
AppLoaderRestClient.GetAsync() 又如下所示:
public static async Task<T> GetAsync<T>(string uri)
{
// ...
if (typeof (T) == typeof (byte[]))
{
var result = await webClient.DownloadDataTaskAsync(uri);
return (T) (object) result;
}
所以,这里实际上有一个任务的链——“内部”任务将是一个任务,然后它将被传播到调用者,并转换为一个任务(即没有结果的任务)。我认为这可能是导致当前问题的原因?
如果我将最外面的代码更改为:
var task = DownloadFileAsync(file, targetFolder, uri);
task.Wait();
...它运行完美。为什么?
有时事实证明,我在将问题发布到此处时设法找到了问题的答案。我想我会分享它来避免其他人头痛......
问题源于我对
dynamic
的使用,或者更确切地说,(在我看来)dynamic
迄今为止在 C#/.NET 中的工作方式略有限制和破坏。如果我像这样改写我的代码:
await (Task)DownloadFileAsync(file, targetFolder, uri);
...它运行完美。
这里的问题是,由于我的参数之一(
file
)是dynamic
,所以这将是一个动态操作。并且返回值似乎在某种程度上因动态操作而“混乱”; CLR 根本无法从上面的代码中推断出该方法是否返回 Task
还是 Task<T>
(或者我猜是这样)。因此,它无法尝试将结果转换为 INotifyCompletion
实例 - 因此,出现异常。
非常感谢很多,微软。 ;)
(我认为这里的主要问题是异常消息非常不清楚,在我看来......)