You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在进度事件中重启Windows.Web.Http.HttpClient的内部取消计时器?

如何在HttpClient进度事件中重启内部取消计时器?

嘿,我明白你的需求了——你希望每次HttpProgress事件触发时,把HttpClient的超时计时器重新归零,避免请求过程中明明还有数据传输却触发超时对吧?

你当前的代码用了CancellationTokenSource(150000)来设置固定超时,但这个构造函数一旦创建,超时时间就没法修改了。要实现“进度触发就重置超时”的效果,我们得换个方式手动管理超时:

核心思路

不用带超时参数的CancellationTokenSource构造函数,而是通过CancelAfter()方法来设置/重置超时。每次进度事件触发时,重新调用CancelAfter(),这样就会覆盖之前的超时设置,相当于把计时器重新拨回150秒。

修改后的完整代码

using (var httpClient = new HttpClient(filter))
using (var httpContent = new HttpStringContent(postBody, UnicodeEncoding.Utf8, content_type))
using (var source = new CancellationTokenSource()) // 不设置初始超时,手动控制
{
    HttpResponseMessage result;
    try
    {
        // 先设置初始的150秒超时,保证请求一开始就有超时保护
        source.CancelAfter(150000);

        result = await httpClient.PostAsync(new Uri(url), httpContent)
            .AsTask(source.Token, new Progress<HttpProgress>(progress => 
            {
                Debug.WriteLine("Progress");
                // 关键:每次进度更新时,重置超时计时器
                source.CancelAfter(150000);
            }));
    }
    catch (TaskCanceledException e)
    {
        // 这里捕获超时(或手动取消)的情况,返回超时响应
        return new ServerRequestResponse(RequestResponseType.Timeout);
    }
    // ...这里添加后续的响应处理逻辑
}

关键细节说明

  • 初始超时设置:在发起请求前必须先调用一次CancelAfter(),否则一开始没有超时限制,不符合你的需求。
  • 重置超时的原理:CancelAfter()会取消之前的超时调度(如果有的话),然后重新安排一个新的150秒后取消的任务,完美实现“进度触发就刷新超时”的效果。
  • 资源释放:用using包裹CancellationTokenSource,确保即使请求抛出异常,资源也能被正确释放。

额外注意

如果你的进度事件触发非常频繁,也不用担心性能问题——CancelAfter()是轻量级操作,内部只是调度了一个延迟任务,不会有明显的性能开销。另外,如果请求已经完成,后续的进度回调(如果有的话)调用CancelAfter()也不会有影响,因为此时任务已经结束,令牌的状态不会再干扰请求流程了。

内容的提问来源于stack exchange,提问作者Vahagn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:00:46