Використовуйте один CancellationToken для заголовків і тіла .NET HttpClient
Передавайте CancellationToken запиту і в підготовку відповіді HttpClient, і в читання тіла, замість того щоб вимірювати лише очікування виклику.
Секундомір може припинити очікування, поки HTTP-запит триває. Передавайте скасування самій операції, коли спроба через проксі має заданий бюджет часу.
Для сучасної програми .NET із наявним HttpClient, налаштованим на проксі:
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 може надходити від переданого токена або від іншого налаштованого тайм-ауту; перевіряйте відповідне джерело скасування, а не оголошуйте кожну невдачу мертвим проксі.
Повторно використовуйте клієнт, якому належить цей проксі-маршрут. Скасування однієї спроби не означає перебудови всього пулу з'єднань для кожного наступного запиту.
Приклад буферизує тіло відповіді скінченного розміру. Під час потокового завантаження токен слід передати через цикл копіювання потоку й звільняти відповідь на кожному шляху виходу.
Скасування виражає політику операції, а не точну обіцянку часу для кожної дії платформи. Не замінюйте його нескінченним циклом опитування Task.IsCompleted.