如何在进度事件中重启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
相关产品推荐
相关产品推荐

