如何为不接受取消令牌的异步函数设置超时? [英] How can I set a timeout for an Async function that doesn't accept a cancellation token?

查看:82
本文介绍了如何为不接受取消令牌的异步函数设置超时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆