秒表可以在 HTTP 请求仍在继续时停止等待。当一次代理尝试有明确的时间预算时,应把取消传给操作本身。

对于已配置好 代理的 HttpClient 的现代 .NET 应用:

using var budget = new CancellationTokenSource(TimeSpan.FromSeconds(5));
using var response = await client.GetAsync(
    targetUrl,
    HttpCompletionOption.ResponseHeadersRead,
    budget.Token);
response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync(budget.Token);

同一个预算在建立响应之前开始,并在读取正文期间持续有效。ResponseHeadersRead 在拿到响应头后就交回控制权,因此 HttpClient 自身的完成超时并不单独决定后续正文读取的预算。

把取消与 HTTP 状态码、传输错误区分开。OperationCanceledException 可能来自传入的 token,也可能来自另一个已配置的超时;应检查对应的取消来源,而不是把每次失败都当成代理已死。

复用持有这条代理路由的客户端。取消一次尝试并不意味着之后每个请求都要重建整个连接池。

示例缓冲的是一个大小有限的响应正文。流式下载应把 token 传入流拷贝循环,并在每条退出路径上释放响应。

取消表达的是一种操作策略,而不是对每个底层平台动作的精确时钟承诺。不要用对 Task.IsCompleted 的无休止轮询来取代它。

相关文章