不等待时TaskCanceledException

时间:2015-07-02 22:08:56

标签: c# asynchronous async-await task

每当我按照When at last you await中的指南同步返回另一个任务而不是等待它时,我似乎得到TaskCanceledException

TaskCanceledException代码

public static class Download
{
    public static Task<byte[]> FromYouTubeAsync(string videoUri)
    {
        using (var client = new HttpClient())
        {
            return FromYouTubeAsync(
                () => client
                .GetStringAsync(videoUri),
                uri => client
                .GetByteArrayAsync(uri));
        }
    }

    public async static Task<byte[]> FromYouTubeAsync(
        Func<Task<string>> sourceFactory, Func<string, Task<byte[]>> downloadFactory)
    {
        string source = await // TaskCanceledException here
            sourceFactory()
            .ConfigureAwait(false);

        // find links

        return await
            downloadFactory(links.First())
            .ConfigureAwait(false);
    }
}

无异常代码

此处,方法签名的第一个重载更改为异步,并等待第二个重载。出于某种原因,这会阻止TaskCanceledException

public static class Download
{
    public async static Task<byte[]> FromYouTubeAsync(string videoUri)
    {
        using (var client = new HttpClient())
        {
            return await FromYouTubeAsync(
                () => client
                .GetStringAsync(videoUri),
                uri => client
                .GetByteArrayAsync(uri));
        }
    }

    public async static Task<byte[]> FromYouTubeAsync(
        Func<Task<string>> sourceFactory, Func<string, Task<byte[]>> downloadFactory)
    {
        string source = await // No exception!
            sourceFactory()
            .ConfigureAwait(false);

        // find links

        return await
            downloadFactory(links.First())
            .ConfigureAwait(false);
    }
}

为什么会发生这种情况,我该怎么做才能修复它(除了等待方法,这会浪费资源,如上面的链接所述)?

1 个答案:

答案 0 :(得分:7)

很抱歉,link you posted是关于应用优化仅当该方法在其await 之后不执行任何操作时才适用。引用帖子:

  

然而,在这种情况下,我们正在处理一个任务来表示方法中的最后一个语句,因此它实际上已经表示了整个方法的处理......

在您的示例中,任务 not 表示方法中的最后一个语句。再看一下:

public async static Task<byte[]> FromYouTubeAsync(string videoUri)
{
  using (var client = new HttpClient())
  {
    return await FromYouTubeAsync(...);
  }
}

await之后发生了一些事情:具体来说,是处置client。因此,博客文章中提到的优化不适用于此

如果您尝试直接返回任务,这就是您看到异常的原因:

public static Task<byte[]> FromYouTubeAsync(string videoUri)
{
  using (var client = new HttpClient())
  {
    return FromYouTubeAsync(...);
  }
}

此代码开始下载,然后处理HttpClient ,然后返回任务。处置后,HttpClient将取消任何未完成的操作。

使用await的代码将(异步)等待HTTP操作在它处理HttpClient之前完成。这就是您需要的行为,await是表达它的最简洁方式。在这种情况下,它不是浪费资源&#34;完全没有,因为你推迟处理,直到下载完成。