3

(質問の本当のタイトルは、「'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;
        }

したがって、実際にはここに Task のチェーンがあります。「内部」Task は Task になり、呼び出し元に伝播され、Task (つまり、結果のない Task) に変換されます。これが目前の問題を引き起こしている可能性があると思いますか?

最も外側のコードを次のように変更すると:

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

...問題なく動作します。なんで?

4

1 に答える 1

13

時々判明することですが、ここに投稿しているときに、質問に対する答えを見つけることができました。他の誰かを頭痛から救うために共有したいと思いました...

この問題は、(私の意見では)まだ C#/.NET で動作するdynamicわずかに制限された壊れた方法の使用に起因しています。dynamicコードを次のように言い換えると:

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

...問題なく動作します。

ここで重要なことは、私のパラメーターの 1 つ ( fileis dynamic) であるため、これは動的な操作になるということです。また、戻り値は、動的操作から何らかの形で「台無し」になっているようです。CLR は、上記のコードから、メソッドが or を返すかどうかを推測することができませんTask(Task<T>またはそう推測します)。したがって、結果をインスタンスにキャストしようとして失敗しINotifyCompletionます - したがって、例外です。

どうもありがとうマイクロソフト。;)
(ここでの主な問題は、私の意見では、例外メッセージが非常に不明確だったことだと思います...)

于 2013-10-03T10:50:52.050 に答える