using Modbus.Device; using ModbusDemo.Model; using ModbusDemo.Uitls; using Prism.Commands; using Prism.Mvvm; using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; namespace ModbusDemo.VIewModel { public class AttachUCViewModel : BindableBase { private SerialPort _serialPort; public DelegateCommand ReadOddRegisterCmm { get; set; } //读取的结果 private string _readResult; public string ReadResult { get { return _readResult; } set { _readResult = value; RaisePropertyChanged(); } } //显示操作的时间 private int _time; public int Time { get { return _time; } set { _time = value; RaisePropertyChanged(); } } public AttachUCViewModel() { } public AttachUCViewModel(SerialPort serialPort) { ReadOddRegisterCmm = new DelegateCommand(ReadOddRegister); _serialPort = serialPort; } /// /// 读1000个寄存器 /// private void ReadOddRegister() { // 创建 Modbus RTU 主站 IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(_serialPort); byte slaveId = 1; ushort totalRegisters = 1000; ushort chunkSize = 100; int numChunks = (int)Math.Ceiling((double)totalRegisters / chunkSize); ushort[] allRegisters = new ushort[totalRegisters]; Task[] tasks = new Task[numChunks]; DateTime startTime = DateTime.Now; for (int i = 0; i < numChunks; i++) { ushort startAddress = (ushort)(10300 + i * chunkSize); ushort currentChunkSize = 100; int chunkIndex = i; tasks[i] = Task.Run(() => { try { ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, currentChunkSize); Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize); } catch (Exception ex) { MessageBox.Show($"线程 {chunkIndex} 读取寄存器时出错: {ex.Message}"); } }); } // 等待所有任务完成 Task.WaitAll(tasks); Time = (int)(DateTime.Now - startTime).TotalMilliseconds; StringBuilder result = new StringBuilder(); int count = 0; for (int i = 1; i < totalRegisters; i += 2) { result.Append(allRegisters[i].ToString() + " "); count++; if (count % 50 == 0) { result.AppendLine(); } } ReadResult = result.ToString(); } /// /// 自己的类 /// private void ReadOddRegister2() { byte slaveId = 1; ushort totalRegisters = 1000; ushort chunkSize = 100; int numChunks = (int)Math.Ceiling((double)totalRegisters / chunkSize); ushort[] allRegisters = new ushort[totalRegisters]; Task[] tasks = new Task[numChunks]; DateTime startTime = DateTime.Now; for (int i = 0; i < numChunks; i++) { ushort startAddress = (ushort)(10300 + i * chunkSize); ushort currentChunkSize = 100; int chunkIndex = i; tasks[i] = Task.Run(async () => { ushort[] registers = await ReadRegisters(slaveId, startAddress, currentChunkSize); Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize); }); } // 等待所有任务完成 Task.WaitAll(tasks); Time = (int)(DateTime.Now - startTime).TotalMilliseconds; StringBuilder result = new StringBuilder(); int count = 0; for (int i = 1; i < totalRegisters; i += 2) { result.Append(allRegisters[i].ToString() + " "); count++; if (count % 50 == 0) { result.AppendLine(); } } ReadResult = result.ToString(); } public async Task ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) { ushort[] resultValue = null; if (!_serialPort.IsOpen) { MessageBox.Show("串口没有链接,请先链接"); return resultValue; } List sendByteList = new List(); //设置从站地址 sendByteList.Add(slaveAddress); //设置功能码 sendByteList.Add(0x03); //设置起始地址的高位和低位 sendByteList.Add(BitConverter.GetBytes(startAddress)[1]); sendByteList.Add(BitConverter.GetBytes(startAddress)[0]); //设置读取几个线圈的高位和低位 sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[1]); sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[0]); //获取CRC校验码 byte[] getCRC = sendByteList.ToArray(); byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); sendByteList.Add(resultCRC[0]); sendByteList.Add(resultCRC[1]); byte[] sendByte = sendByteList.ToArray(); int maxRetries = 3; // 最大重试次数 int attempt = 0; List responseData = new List(); byte[] response = null; _serialPort.Write(sendByte, 0, sendByte.Length); while (attempt < maxRetries) { try { //使用时间去轮询查询数据 DateTime startTime = DateTime.Now; while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) { int bytesToRead = _serialPort.BytesToRead; if (bytesToRead > 0) { byte[] buffer = new byte[bytesToRead]; int bytesRead = _serialPort.Read(buffer, 0, bytesToRead); responseData.AddRange(buffer.Take(bytesRead)); } //延迟20毫秒,节约cpu资源 await Task.Delay(20); } response = responseData.ToArray(); if (response[0] == 0x00) { continue; } resultValue = ParseRegistersresponse(sendByte, response, numberOfPoints); return resultValue; } catch (Exception) { attempt++; } } return resultValue; } public ushort[] ParseRegistersresponse(byte[] sendByte, byte[] response, ushort numberOfPoints) { //判断发送回来的数据是否正确 if (CheckData.CheckResponse(response)) { ushort[] registers = new ushort[numberOfPoints]; for (int i = 0; i < numberOfPoints; i++) { int pos = 3 + i * 2; // 大端序转换 (高位在前) registers[i] = (ushort)((response[pos] << 8) | response[pos + 1]); } return registers; } else { return null; } } } }