每当我按照When at last you await中的指南同步返回另一个任务而不是等待它时,我似乎得到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);
}
}
为什么会发生这种情况,我该怎么做才能修复它(除了等待方法,这会浪费资源,如上面的链接所述)?
答案 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;完全没有,因为你有推迟处理,直到下载完成。