不等待时TaskCanceledException
每当我同步返回另一个任务而不是等待它时,我似乎得到一个TaskCanceledException
,遵循最后等待时的指导原则。
TaskCanceledException代码
public static class Download { public static Task FromYouTubeAsync(string videoUri) { using (var client = new HttpClient()) { return FromYouTubeAsync( () => client .GetStringAsync(videoUri), uri => client .GetByteArrayAsync(uri)); } } public async static Task FromYouTubeAsync( Func<Task> sourceFactory, Func<string, Task> downloadFactory) { string source = await // TaskCanceledException here sourceFactory() .ConfigureAwait(false); // find links return await downloadFactory(links.First()) .ConfigureAwait(false); } }
无exception代码
这里,方法签名的第一个重载更改为async,它等待第二个重载。 出于某种原因,这可以防止TaskCanceledException
。
public static class Download { public async static Task FromYouTubeAsync(string videoUri) { using (var client = new HttpClient()) { return await FromYouTubeAsync( () => client .GetStringAsync(videoUri), uri => client .GetByteArrayAsync(uri)); } } public async static Task FromYouTubeAsync( Func<Task> sourceFactory, Func<string, Task> downloadFactory) { string source = await // No exception! sourceFactory() .ConfigureAwait(false); // find links return await downloadFactory(links.First()) .ConfigureAwait(false); } }
为什么会发生这种情况,我该怎么做才能解决它( 除了等待上面链接中描述的浪费资源的方法)?
抱歉, 您发布的链接是关于应用优化的 , 只有在方法await
之后该方法await
时才适用 。 引用post:
然而,在这种情况下,我们正在处理一个任务来表示方法中的最后一个语句,因此它实际上已经表示了整个方法的处理…
在您的示例中,该任务不代表方法中的最后一个语句。 再看一遍:
public async static Task FromYouTubeAsync(string videoUri) { using (var client = new HttpClient()) { return await FromYouTubeAsync(...); } }
await
之后发生了一些事情:特别是处理client
。 因此,该博客文章中提到的优化不适用于此处 。
这就是您尝试直接返回任务时看到exception的原因:
public static Task FromYouTubeAsync(string videoUri) { using (var client = new HttpClient()) { return FromYouTubeAsync(...); } }
此代码开始下载, 然后处理HttpClient
,然后返回任务。 HttpClient
将在处置时取消任何未完成的操作。
使用await
的代码将(异步)等待HTTP操作在它处理HttpClient
之前完成。 这就是你需要的行为, await
是表达它的最干净的方式。 在这种情况下,它根本不是“浪费资源”,因为在下载完成之前,您必须推迟处置。