不等待时出现 TaskCanceledException
TaskCanceledException when not awaiting
每当我同步 return 另一个任务而不是等待它时,我似乎都会收到 TaskCanceledException
,遵循 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);
}
}
为什么会发生这种情况,我能做些什么来解决它(除了等待方法,这会浪费资源,如上面link所述)?
抱歉,link you posted 是关于应用优化,仅当方法在其 await
[ 之后不执行任何操作时才适用=41=]。引用 post:
In this case, however, we’re being handed a task to represent the last statement in the method, and thus it’s in effect already a representation of the entire method’s processing...
在您的示例中,任务不表示方法中的最后一条语句。再看:
public async static Task<byte[]> FromYouTubeAsync(string videoUri)
{
using (var client = new HttpClient())
{
return await FromYouTubeAsync(...);
}
}
await
之后发生了一些事情:特别是 client
的处置。所以那个博客里提到的优化post在这里不适用.
这就是您在尝试直接 return 任务时看到异常的原因:
public static Task<byte[]> FromYouTubeAsync(string videoUri)
{
using (var client = new HttpClient())
{
return FromYouTubeAsync(...);
}
}
此代码开始下载,然后处理 HttpClient
,然后 return 执行任务。 HttpClient
将在处置时取消任何未完成的操作。
使用 await
的代码将(异步地)等待 HTTP 操作完成,然后再处理 HttpClient
。这就是您需要的行为,而 await
是最简洁的表达方式。在这种情况下,它根本不是 "waste of resources",因为您 必须 将处理推迟到下载完成后。
每当我同步 return 另一个任务而不是等待它时,我似乎都会收到 TaskCanceledException
,遵循 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);
}
}
为什么会发生这种情况,我能做些什么来解决它(除了等待方法,这会浪费资源,如上面link所述)?
抱歉,link you posted 是关于应用优化,仅当方法在其 await
[ 之后不执行任何操作时才适用=41=]。引用 post:
In this case, however, we’re being handed a task to represent the last statement in the method, and thus it’s in effect already a representation of the entire method’s processing...
在您的示例中,任务不表示方法中的最后一条语句。再看:
public async static Task<byte[]> FromYouTubeAsync(string videoUri)
{
using (var client = new HttpClient())
{
return await FromYouTubeAsync(...);
}
}
await
之后发生了一些事情:特别是 client
的处置。所以那个博客里提到的优化post在这里不适用.
这就是您在尝试直接 return 任务时看到异常的原因:
public static Task<byte[]> FromYouTubeAsync(string videoUri)
{
using (var client = new HttpClient())
{
return FromYouTubeAsync(...);
}
}
此代码开始下载,然后处理 HttpClient
,然后 return 执行任务。 HttpClient
将在处置时取消任何未完成的操作。
使用 await
的代码将(异步地)等待 HTTP 操作完成,然后再处理 HttpClient
。这就是您需要的行为,而 await
是最简洁的表达方式。在这种情况下,它根本不是 "waste of resources",因为您 必须 将处理推迟到下载完成后。