当前位置: 首页 > 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.gsyq.cn/news/41739.html

相关文章:

  • 2025年石墨增碳剂搅拌机源头厂家权威推荐:塑料粉混合机/厚型防火涂料搅拌机混合机/灌浆料搅拌机设备厂商精选
  • 2025年粉末涂料最新权威排行榜TOP10,行业新启航
  • 2025年11月学习机品牌对比榜:从早教到高中全场景机型盘点
  • 2025 年合金管公司最新推荐榜权威发布:12Cr1MoVG/15CrMoG/P22 合金管优质企业榜单及选择指南
  • re-catch
  • 2025 年颗粒灌装机源头厂家最新推荐榜:涵盖全自动、双头、四头、杂粮等多类型设备,助力企业精准选优质生产商
  • 激光驱动器技术:精密控制与创新应用
  • 2025年南京苹果售后维修点推荐:高性价比门店名单与选择策略
  • springboot 下的Thymeleaf 前端渲染引擎
  • 2025年泉州苹果售后维修点推荐:主流门店列表与选择方案
  • 利用keil +RASC给瑞萨RA8D1编译烧写软件
  • Gitee:中国DevSecOps实践的标杆与未来
  • MyEMS:智能化能源管理的创新实践者
  • 2025年抖音SEO排名推荐:市场报告揭示的头部解决方案
  • 2025年精密精轧管生产厂家权威推荐榜单:不锈钢管精轧管/冷拔管精轧管/精轧焊管源头厂家精选
  • 还在担心文件泄露?这个浏览器里的格式转换工具,给了另一种答案
  • 2025年11月效果图公司推荐榜:权威评测五强排名与横向对比
  • psql -U PostgreSQL端命令
  • Linux V4L2框架详解:Camera软件架构与驱动达成
  • 简单接口并发测试
  • 2025 年白炭黑生产厂家最新推荐排行榜:涵盖微珠 / 疏水 / 气相法 / 沉淀法等多类型产品,权威测评选出优质企业供下游参考二氧化硅/胶粉用白炭黑公司推荐
  • 2025年11月中国GEO平台推荐排行榜:AI搜索优化技术全面解析
  • 【Linux dbus】问题解决 Failed to connect to socket /run/user/1000/bus: No such file or directory
  • Windows系统真随机数生成器实现
  • 2025年11月沈阳代理记账公司排行榜:专业顾问的深度推荐
  • Chronic disease
  • 11.6 1.基础HTTPGET接口请求测试
  • 2025年11月学习机品牌推荐榜:清北双师与AI精准学排行盘点
  • Linux - 压缩解压篇
  • P2416 泡芙 题解