当前位置: 首页 > news >正文

近期小细节总结

串口并发调用

单个串口通讯(Modbus RTU也算),业务流程中的串口调用,既有定时轮询又有依次发送,也就是涉及到并发调用通讯的,不要犹豫,为通讯管理模块建立消息队列

  • 不用纠结锁的问题,天然线程安全

  • 定时任务和手动操作随便调用,自动排队

// 请求队列
private readonly Channel<ModbusRequest> _requestChannel = Channel.CreateBounded<ModbusRequest>(20);
private readonly CancellationTokenSource _processingCts = new CancellationTokenSource();
private Task _processingTask;// 添加请求类private class ModbusRequest{public byte DeviceAddress { get; set; }public byte FunctionCode { get; set; }public ushort RegisterAddress { get; set; }public ushort Value { get; set; }public ushort RegisterCount { get; set; }public TaskCompletionSource<byte[]> CompletionSource { get; set; }}// 启动请求处理任务_processingTask = Task.Run(ProcessModbusRequests);/// <summary>/// Modbus命令内部实现(无锁版本)/// </summary>private async Task<byte[]> SendModbusCommandInternal(byte deviceAddress, byte functionCode, ushort registerAddress, ushort value = 0, ushort registerCount = 1){try{// 构建请求帧(原SendModbusCommand的逻辑移到这里)byte[] request;if (functionCode == 0x03) // 读取保持寄存器
                {request = new byte[6];request[0] = deviceAddress;request[1] = functionCode;request[2] = (byte)(registerAddress >> 8);request[3] = (byte)(registerAddress & 0xFF);request[4] = (byte)(registerCount >> 8);request[5] = (byte)(registerCount & 0xFF);}else if (functionCode == 0x06) // 写单个寄存器
                {request = new byte[6];request[0] = deviceAddress;request[1] = functionCode;request[2] = (byte)(registerAddress >> 8);request[3] = (byte)(registerAddress & 0xFF);request[4] = (byte)(value >> 8);request[5] = (byte)(value & 0xFF);}else{throw new ArgumentException($"不支持的功能码: {functionCode}");}// 添加CRC校验byte[] crc = CalculateCRC(request);byte[] fullRequest = new byte[request.Length + 2];Array.Copy(request, fullRequest, request.Length);fullRequest[request.Length] = crc[0];fullRequest[request.Length + 1] = crc[1];// 清空缓冲区
                _serialPort.DiscardInBuffer();_serialPort.DiscardOutBuffer();// 发送请求IoC.Get<MessageManagement>().AddMessage($"Write: {BitConverter.ToString(fullRequest).Replace("-", " ")}");_serialPort.Write(fullRequest, 0, fullRequest.Length);// 异步读取响应return await ReadModbusResponse();}catch (Exception ex){IoC.Get<MessageManagement>().AddMessage($"Modbus通信失败: {ex.Message}", MessageType.警告);return null;}}/// <summary>/// 异步读取Modbus响应/// </summary>private async Task<byte[]> ReadModbusResponse(){await Task.Delay(500); // 等待设备响应
List<byte> response = new List<byte>();DateTime startTime = DateTime.Now;while (DateTime.Now - startTime < TimeSpan.FromMilliseconds(READ_TIMEOUT)){if (_serialPort.BytesToRead > 0){byte[] buffer = new byte[_serialPort.BytesToRead];int bytesRead = _serialPort.Read(buffer, 0, buffer.Length);response.AddRange(buffer.Take(bytesRead));// 检查是否收到完整帧if (response.Count >= 5) // 最小响应长度
                    {// 验证CRCbyte[] receivedData = response.ToArray();byte[] receivedCRC = new byte[] { receivedData[receivedData.Length - 2], receivedData[receivedData.Length - 1] };byte[] calculatedCRC = CalculateCRC(receivedData.Take(receivedData.Length - 2).ToArray());if (receivedCRC[0] == calculatedCRC[0] && receivedCRC[1] == calculatedCRC[1]){return receivedData;}else{IoC.Get<MessageManagement>().AddMessage($"CRC error: {BitConverter.ToString(receivedData).Replace("-", " ")}");}}}await Task.Delay(10);}throw new TimeoutException("读取响应超时");}/// <summary>/// 发送Modbus命令(队列版本)/// </summary>private async Task<byte[]> SendModbusCommand(byte deviceAddress, byte functionCode, ushort registerAddress, ushort value = 0, ushort registerCount = 1){var request = new ModbusRequest{DeviceAddress = deviceAddress,FunctionCode = functionCode,RegisterAddress = registerAddress,Value = value,RegisterCount = registerCount,CompletionSource = new TaskCompletionSource<byte[]>()};// 修复:使用带CancellationToken的WaitToWriteAsyncif (await _requestChannel.Writer.WaitToWriteAsync(_processingCts.Token)){await _requestChannel.Writer.WriteAsync(request, _processingCts.Token);// 使用带超时的Task等待using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(30));var timeoutTask = Task.Delay(Timeout.Infinite, timeoutCts.Token);var responseTask = request.CompletionSource.Task;var completedTask = await Task.WhenAny(responseTask, timeoutTask);if (completedTask == responseTask){return await responseTask;}else{throw new TimeoutException("Modbus操作超时");}}else{throw new TimeoutException("Modbus请求队列已满");}}/// <summary>/// 读取保持寄存器/// </summary>async private Task<ushort[]> ReadHoldingRegisters(byte deviceAddress, ushort startAddress, ushort registerCount){byte[] response = await SendModbusCommand(deviceAddress, 0x03, startAddress, 0, registerCount);if (response != null && response.Length >= 5 + registerCount * 2){ushort[] result = new ushort[registerCount];for (int i = 0; i < registerCount; i++){int offset = 3 + i * 2;result[i] = (ushort)((response[offset] << 8) | response[offset + 1]);}return result;}return null;}/// <summary>/// 写单个寄存器/// </summary>async private Task<bool> WriteSingleRegister(byte deviceAddress, ushort registerAddress, ushort value){byte[] response = await SendModbusCommand(deviceAddress, 0x06, registerAddress, value);return response != null && response.Length >= 6;}

 

CPU占用

减少Task.Factory.StartNew,线程池都给干满了,非必要不要用

http://www.jsqmd.com/news/33110/

相关文章:

  • pytorch汉字识别
  • 2025年泵站闸门定制厂家权威推荐榜单:截流闸门/分流井闸门/截流井污水闸门源头厂家精选
  • 2025年石墨增碳剂搅拌机源头厂家权威推荐:塑料粉混合机/厚型防火涂料搅拌机混合机/灌浆料搅拌机设备厂商精选
  • 深入理解浮点数格式:FP32、BF16、FP16与FP8的技术对比 - 详解
  • 2025年粉末涂料最新权威排行榜TOP10,行业新启航
  • 2025年11月小学生学习机品牌推荐:五强口碑榜与选购指南
  • 详细介绍:Java 数学类详解:Math 类常用方法(abs/sqrt/random 等)一篇掌握
  • Ubuntu环境下删除Docker镜像与容器、配置静态IP地址
  • 2025 年管线管公司最新推荐排行榜:权威测评发布,揭秘行业前五强综合实力及选购指南L245N 管线管/L360N 管线管/L415N 管线管公司推荐
  • 2025年11月学习机品牌对比榜:从早教到高中全场景机型盘点
  • 2025年湖南房屋鉴定公司权威推荐榜单:湖南房屋鉴定报告/湖南房屋鉴定机构/湖南房屋安全检测服务机构精选
  • 2025 年合金管公司最新推荐榜权威发布:12Cr1MoVG/15CrMoG/P22 合金管优质企业榜单及选择指南
  • 2025年发电电焊机工厂权威推荐:柴油焊机/汽油焊机/柴油发电电焊机源头厂家精选
  • 2025 年电线电缆实力厂家最新推荐榜单:结合协会测评权威数据,精选优质企业赋能工程与民生采购阻燃 / 耐火 / 屏蔽 / 低烟 / 电子和网络电缆电线推荐
  • 2025 年度茶叶优质品牌权威榜单发布,最新推荐品牌核心优势全解析助消费者选对好茶
  • 企业自研低代码,为什么常常走不通?
  • 2025年逆流闭式冷却塔制造企业权威推荐榜单:复合流闭式冷却塔/工业闭式冷却塔/横流式闭式冷却塔源头厂家精选
  • re-upx
  • 2025年工程机械润滑油厂商权威推荐:风电设备专用润滑油/钢铁行业润滑油/化工行业润滑油源头供应商精选
  • Windows10系统离线安装.NET Framework 3.5的方法-cab文件安装法 - 阳光宝贝
  • 2025年防霉涂料直销厂家权威推荐榜单:防潮涂料/洁净涂料/硅晶釉涂源头供应商精选
  • MySQL索引类型及其应用
  • re-catch
  • Unity后处理胶片颗粒FilmGrain技术全解析
  • 最长递增子序列(LIS)深度解析:从动态规划到贪心+二分
  • 2025 年颗粒灌装机源头厂家最新推荐榜:涵盖全自动、双头、四头、杂粮等多类型设备,助力企业精准选优质生产商
  • 2025 年彩灯源头厂家最新推荐排行榜权威发布,涵盖节日 / 生肖 / 大型户外等全品类彩灯定制,实力标杆厂家详细测评
  • 2025 年最新推荐花灯源头厂家权威排行榜:全产业链实力企业甄选 + 20000 平厂房厂家名单发布大型手工花灯/春节花灯/元宵节花灯公司推荐
  • 2025 年旋转接头源头厂家最新推荐榜:液压 / 高温 / 非标等多类型产品权威测评及优质企业盘点
  • 小程序认证费:如何可以省下这小程序认证费用?