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

如何在HttpClient请求取消前获取并处理已接收的数据?

实现可取消且保留已接收数据的HTTP流请求

可以实现这个需求。问题出在你直接将CancellationToken传递给了GetStreamAsync,此时取消令牌触发时会直接终止整个请求并抛出OperationCanceledException。要保留已接收的数据,需要把取消逻辑移到流读取的环节,而非请求初始化阶段。

解决方案步骤:

  • 改用HttpClient.SendAsync方法,并指定HttpCompletionOption.ResponseHeadersRead,这样能在响应头返回后立即拿到流,无需等待整个响应完成。
  • 在读取流的循环中,主动检查取消令牌状态;一旦检测到取消,就停止读取,但保留之前已经读取到的数据。
  • 避免将取消令牌直接传递给请求方法,而是在读取过程中手动控制。

修改后的代码示例:

private CancellationTokenSource cts = new CancellationTokenSource();
// 用于存储已接收的数据
private List<byte> receivedData = new List<byte>();

private async void button1_Click(object sender, EventArgs e)
{
    receivedData.Clear();
    HttpClient client = new HttpClient();
    try
    {
        // 发送请求,仅等待响应头返回
        var request = new HttpRequestMessage(HttpMethod.Get, url);
        var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
        response.EnsureSuccessStatusCode();

        using (var stream = await response.Content.ReadAsStreamAsync())
        {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                // 检查是否取消,若取消则退出循环
                if (cts.Token.IsCancellationRequested)
                {
                    break;
                }
                // 将读取到的数据存入集合
                receivedData.AddRange(buffer.Take(bytesRead));
            }
        }

        // 无论是否取消,都处理已接收的数据
        ProcessReceivedData(receivedData);
    }
    catch (OperationCanceledException ex)
    {
        // 此处异常仅来自SendAsync的主动取消(若需保留可用于日志)
    }
    finally
    {
        // 重置取消令牌源,以便下次请求使用
        cts.Dispose();
        cts = new CancellationTokenSource();
    }
}

private void button2_Click(object sender, EventArgs e)
{
    cts.Cancel();
}

// 处理已接收数据的方法
private void ProcessReceivedData(List<byte> data)
{
    // 这里写你的数据处理逻辑,比如转字符串、解析等
    string content = Encoding.UTF8.GetString(data.ToArray());
    // ...
}

关键说明:

  • HttpCompletionOption.ResponseHeadersRead让我们能尽早获取流,开始读取数据,而不是等整个响应下载完成。
  • 在流读取循环中检查cts.Token.IsCancellationRequested,一旦触发就跳出循环,此时receivedData已经保存了取消前读取到的所有数据。
  • 最后统一处理已接收的数据,无论请求是否被取消,都能正常执行这部分逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 00:22:43