阶段性批量提交

This commit is contained in:
2026-01-05 14:54:06 +08:00
parent 917d76a87f
commit a697aab3e0
21 changed files with 1479 additions and 379 deletions

View File

@@ -0,0 +1,63 @@
using System.Threading.Channels;
namespace SHH.CameraService;
/// <summary>
/// 视频数据高速通道
/// <para>作用:解耦 采集线程(Producer) 和 发送线程(Consumer)</para>
/// <para>特性:使用 BoundedChannel当网络发送慢时自动丢弃旧帧(DropOldest),防止内存溢出。</para>
/// </summary>
public class VideoDataChannel
{
// 创建一个有限容量的通道 (容量 5)
// 如果发送端太慢这就满了DropOldest 会丢弃最旧的帧,保证实时性
private readonly Channel<VideoPayload> _channel = Channel.CreateBounded<VideoPayload>(
new BoundedChannelOptions(5)
{
FullMode = BoundedChannelFullMode.DropOldest, // 核心策略:丢弃旧帧
SingleReader = true, // 只有一个 ZeroMQWorker 在读
SingleWriter = false //可能有多个相机线程在写
});
// ★★★ 新增:公开 Reader 属性,让外部可以直接调用 ReadAsync ★★★
public ChannelReader<VideoPayload> Reader => _channel.Reader;
/// <summary>
/// 写入数据 (生产者调用)
/// </summary>
public ValueTask WriteAsync(VideoPayload payload)
{
return _channel.Writer.WriteAsync(payload);
}
/// <summary>
/// 读取数据流 (消费者调用)
/// </summary>
public IAsyncEnumerable<VideoPayload> ReadAllAsync(CancellationToken ct)
{
return _channel.Reader.ReadAllAsync(ct);
}
}
// 附带:如果您的项目中还没有定义 VideoPayload这里是一个最小实现
// 如果 SHH.Contracts 中已有,请忽略此类
public class VideoPayload
{
/// <summary> 相机唯一标识 </summary>
public string CameraId { get; set; } = string.Empty;
/// <summary> 采集时间 </summary>
public DateTime CaptureTime { get; set; }
/// <summary> 发送时间 </summary>
public DateTime DispatchTime { get; set; }
/// <summary> 原始宽 </summary>
public int OriginalWidth { get; set; }
/// <summary> 原始高 </summary>
public int OriginalHeight { get; set; }
/// <summary> 已编码的图片数据 (JPG) </summary>
public byte[] OriginalImageBytes { get; set; } = Array.Empty<byte>();
}