如何为不接受取消令牌的异步函数设置超时? [英] How can I set a timeout for an Async function that doesn't accept a cancellation token?
问题描述
我的Web请求由此代码处理;
I have my web requests handled by this code;
Response = await Client.SendAsync(Message, HttpCompletionOption.ResponseHeadersRead, CToken);
在读取响应标头之后和内容读取完成之前返回。当我调用此行获取内容时……
That returns after the response headers are read and before the content is finished reading. When I call this line to get the content...
return await Response.Content.ReadAsStringAsync();
我希望能够在X秒后停止它。但是它不接受取消令牌。
I want to be able to stop it after X seconds. But it doesn't accept a cancellation token.
推荐答案
尽管您可以依靠 WithCancellation
用于重用,一个更简单的超时解决方案(不会抛出 OperationCanceledException
)将是使用以下方法创建超时任务 Task.Delay
并使用 Task.WhenAny
:
While you can rely on WithCancellation
for reuse purposes, a simpler solution for a timeout (which doesn't throw OperationCanceledException
) would be to create a timeout task with Task.Delay
and wait for the first task to complete using Task.WhenAny
:
public static Task<TResult> WithTimeout<TResult>(this Task<TResult> task, TimeSpan timeout)
{
var timeoutTask = Task.Delay(timeout).ContinueWith(_ => default(TResult), TaskContinuationOptions.ExecuteSynchronously);
return Task.WhenAny(task, timeoutTask).Unwrap();
}
或者,如果您想抛出异常,以防超时而不是只是返回默认值(即 null
):
Or, if you want to throw an exception in case there's a timeout instead of just returning the default value (i.e. null
):
public static async Task<TResult> WithTimeout<TResult>(this Task<TResult> task, TimeSpan timeout)
{
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
{
return await task;
}
throw new TimeoutException();
}
用法为:
var content = await Response.Content.ReadAsStringAsync().WithTimeout(TimeSpan.FromSeconds(1));
这篇关于如何为不接受取消令牌的异步函数设置超时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!