为什么InvalidCastException的时候正待任务返回方法?正待、任务、时候、方法

2023-09-03 01:08:43 作者:撩妹用语

(问题的真正标题应该是为什么我得到无法投类型的对象System.Runtime.CompilerServices.TaskAwaiter`1 [System.Runtime.CompilerServices.VoidTaskResult]'输入'系统。 Runtime.CompilerServices.INotifyCompletion',但不幸的是,这是太长了计算器:)

(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. :)

您好,

我试图时变得非常奇特的问题接踵而至我的一个方法的执行。调用code如下(节选):

I'm getting really peculiar problems when trying to await the execution of a method of mine. The calling code looks like this (excerpt):

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

在DownloadFileAsync看起来是这样的:

The DownloadFileAsync looks like this:

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

在AppLoaderRestClient.GetAsync(),反过来,看起来是这样的:

The AppLoaderRestClient.GetAsync(), in turn, looks like this:

    public static async Task<T> GetAsync<T>(string uri)
    {
        // ...
        if (typeof (T) == typeof (byte[]))
        {
            var result = await webClient.DownloadDataTaskAsync(uri);
            return (T) (object) result;
        }

所以,其实是有链的任务在这里 - 内部任务将是一个任务,然后将被传播到调用者,并将其转换为一个任务(即任务无的结果)。我presume这可能手头会造成这个问题?

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 (i.e. a Task without a result). I presume this could be causing the issue at hand?

如果我更改最外面的code到这一点:

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...

这是我使用的动态,或者更确切地说,问题的根源时,(在我看来)轻度受限和破碎的方式动态作品在C#/。NET的呢。如果我重新整理我的code是这样的:

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. If I rephrase my code like this:

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

...它完美的作品。

...it works flawlessly.

下面的事情是,因为我的参数之一(文件是动态的),这将是一个动态操作。和返回值似乎被某种方式从动态操作搞砸了; CLR的是根本无法从code来推断上述是否该方法返回工作任务&LT; T&GT; (左右我猜)。因此,它失败尝试的结果强制转换为INotifyCompletion实例 - 因此,除了

The thing here is that since one of my parameters (file is dynamic), this will be a dynamic operation. 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). It therefore fails trying to cast the result to an INotifyCompletion instance - hence, the exception.

感谢的很多的微软。 ;) (我觉得这里的主要问题是,异常消息是很清楚,在我看来...)

Thanks a lot, Microsoft. ;) (I think the main problem here is that the exception message was very unclear, in my opinion...)