简体   繁体   English

为什么在等待任务返回方法时出现InvalidCastException?

[英]Why InvalidCastException when awaiting Task-returning method?

(The real title of the question should be "Why do I get a 'Unable to cast object of type 'System.Runtime.CompilerServices.TaskAwaiter`1[System.Runtime.CompilerServices.VoidTaskResult]' to type 'System.Runtime.CompilerServices.INotifyCompletion'", but unfortunately this is too long for StackOverflow. :) (问题的真正标题应该是“为什么我得到一个'无法播放'System.Runtime.CompilerServices.TaskAwaiter`1 [System.Runtime.CompilerServices.VoidTaskResult]'类型的对象'来键入'System.Runtime.CompilerServices .INotifyCompletion'“,但遗憾的是这对StackOverflow来说太长了。:)

Hi, 嗨,

I'm getting really peculiar problems when trying to await the execution of a method of mine. 当我试图await执行我的方法时,我遇到了一些特殊的问题。 The calling code looks like this (excerpt): 调用代码看起来像这样(摘录):

    private async Task DownloadAddonFileAsync(dynamic addon, dynamic file, string targetFolder)
    {
        // ...
        await DownloadFileAsync(file, targetFolder, uri);

The DownloadFileAsync looks like this: DownloadFileAsync看起来像这样:

    protected async Task DownloadFileAsync(dynamic file, string targetFolder, string uri)
    {
        // ...
        var fileBytes = await AppLoaderRestClient.GetAsync<byte[]>(uri);

The AppLoaderRestClient.GetAsync(), in turn, looks like this: 反过来,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;
        }

So, there is actually a chain of Tasks here - the "inner" Task will be a Task, which will then be propagated up to the caller, and converted to a Task (ie a Task without a result). 因此,这里实际上存在一系列任务 - “内部”任务将是一个任务,然后将其传播到调用者,并转换为任务(即没有结果的任务)。 I presume this could be causing the issue at hand? 我认为这可能导致手头的问题?

If I change the outermost code to this: 如果我将最外面的代码更改为:

        var task = DownloadFileAsync(file, targetFolder, uri);
        task.Wait();

...it works flawlessly. ......它完美无瑕。 Why? 为什么?

As it sometimes turns out, I managed to find out the answer to the question while posting it here. 有时候结果是,我在这里发布时设法找到问题的答案。 Thought I'd share it to save someone else from headache... 以为我会分享它以避免让别人头疼...

The problem stems from my use of dynamic , or rather, the (in my opinion) slightly limited and broken way dynamic works in C#/.NET as of yet. 这个问题源于我使用dynamic ,或者更确切地说,(在我看来)C#/ .NET中的dynamic作品略有限制和破碎。 If I rephrase my code like this: 如果我像这样重新编写代码:

await (Task)DownloadFileAsync(file, targetFolder, uri);

...it works flawlessly. ......它完美无瑕。

The thing here is that since one of my parameters ( file is dynamic ), this will be a dynamic operation. 这里的事情是,由于我的一个参数( filedynamic ),这将是一个动态操作。 And return values seem to be somehow "messed up" from dynamic operations; 并且返回值似乎以某种方式“混乱”来自动态操作; the CLR is simply unable to deduce from the code above whether the method returns Task or Task<T> (or so I guess). CLR根本无法从上面的代码中推断出该方法是返回Task还是Task<T> (或者我猜)。 It therefore fails trying to cast the result to an INotifyCompletion instance - hence, the exception. 因此,它无法尝试将结果转换为INotifyCompletion实例 - 因此,异常。

Thanks a lot , Microsoft. 非常感谢,微软。 ;) ;)
(I think the main problem here is that the exception message was very unclear, in my opinion...) (我认为这里的主要问题是异常信息非常不清楚,在我看来......)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM