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

如何在C#中计算List<T>的字节大小以实现批量发送?

分批发送大型List的实现方案

完全可以通过运行时计算每个对象序列化后的字节大小并累加,来精准控制批次的JSON字节数,避免超过服务端的6Mb限制。以下是具体实现思路和代码改造方案:

核心思路

由于对象存在多层嵌套,直接估算内存占用无法精准对应JSON序列化后的字节数,因此实际序列化单个对象并计算其UTF-8字节数是最可靠的方式。同时要把JSON数组的结构开销(如[]和对象间的逗号)纳入计算,确保最终批次序列化后的总大小不超过预设阈值。

具体实现步骤

  1. 设定批次字节阈值(建议设为4.8~5Mb,预留少量余量)
  2. 遍历原List,逐个计算对象序列化后的字节数
  3. 累加字节数(包含数组结构开销),当加入当前对象会超过阈值时,立即发送当前批次并开启新批次
  4. 处理遍历结束后剩余的最后一批对象

代码改造示例

基于你现有的Newtonsoft.Json代码,改造如下:

1. 计算单个对象序列化后的字节数(优化版)

避免先序列化字符串再转字节的额外开销,直接通过内存流计算:

private long GetObjectJsonByteSize<T>(T obj)
{
    using (var memoryStream = new MemoryStream())
    using (var jsonWriter = new JsonTextWriter(new StreamWriter(memoryStream, Encoding.UTF8)))
    {
        var serializer = new JsonSerializer();
        serializer.Serialize(jsonWriter, obj);
        jsonWriter.Flush();
        return memoryStream.Length;
    }
}

2. 分批处理与发送逻辑

// 配置参数
var maxBatchBytes = 4_800_000; // 4.8Mb,预留余量避免超限制
var authToken = "你的授权Token";
var targetUrl = "目标Web服务地址";

var currentBatch = new List<T>();
long currentBatchTotalBytes = 2; // 初始为JSON数组的[],占2字节

using (var httpClient = new HttpClient())
{
    foreach (var item in list)
    {
        var itemBytes = GetObjectJsonByteSize(item);
        // 计算加入当前对象需要增加的字节数:非空批次需加逗号(1字节)+ 对象字节数
        var addedBytes = currentBatch.Count > 0 ? 1 + itemBytes : itemBytes;

        if (currentBatchTotalBytes + addedBytes <= maxBatchBytes)
        {
            currentBatch.Add(item);
            currentBatchTotalBytes += addedBytes;
        }
        else
        {
            // 发送当前批次
            await SendBatch(currentBatch, targetUrl, authToken, httpClient);
            // 重置批次,加入当前对象
            currentBatch.Clear();
            currentBatch.Add(item);
            currentBatchTotalBytes = 2 + itemBytes; // [] + 当前对象字节数
        }
    }

    // 发送最后一批剩余对象
    if (currentBatch.Count > 0)
    {
        await SendBatch(currentBatch, targetUrl, authToken, httpClient);
    }
}

// 封装批次发送方法
private async Task SendBatch<T>(List<T> batch, string url, string authToken, HttpClient client)
{
    var jsonContent = JsonConvert.SerializeObject(batch);
    var request = new HttpRequestMessage(HttpMethod.Post, url)
    {
        Content = new StringContent(jsonContent, Encoding.UTF8, "application/json")
    };
    request.Headers.Add("Authorization", $"Bearer {authToken}");

    var response = await client.SendAsync(request);
    // 可根据需求添加响应校验或处理逻辑
    response.EnsureSuccessStatusCode();
    var responseJson = await response.Content.ReadAsStringAsync();
    // 这里可以记录日志、处理返回结果等
}

注意事项

  • 结构开销计算:JSON数组的[]占2字节,每个对象之间的逗号占1字节,这些必须纳入总字节数计算,否则会出现实际序列化后超标的情况。
  • 性能优化:使用内存流计算字节数的方式,比先序列化字符串再计算更高效,尤其适合大量对象的场景。
  • 阈值预留:不要把阈值设为刚好5Mb,预留200KB左右的余量,避免因序列化时的细微差异(如空格、转义字符)导致超限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:53:11