一、核心架构设计
主线程
SerialPortManager
接收线程
发送线程
数据缓冲队列
数据处理线程
二、关键代码实现
1. 串口管理类(线程安全封装)
csharp
using System.IO.Ports;
using System.Threading;
using System.Collections.Concurrent;
public class SerialPortManager : IDisposable
{
private SerialPort _serialPort;
private Thread _readThread;
private Thread _writeThread;
private ConcurrentQueue<byte[]> _dataQueue = new ConcurrentQueue<byte[]>();
private AutoResetEvent _writeEvent = new AutoResetEvent(false);
private SemaphoreSlim _serialLock = new SemaphoreSlim(1, 1);
public event Action<byte[]> DataReceived;
public SerialPortManager(string portName, int baudRate)
{
InitializePort(portName, baudRate);
StartThreads();
}
private void InitializePort(string portName, int baudRate)
{
_serialPort = new SerialPort(portName, baudRate)
{
Parity = Parity.None,
DataBits = 8,
StopBits = StopBits.One,
ReadTimeout = 500,
WriteTimeout = 500
};
_serialPort.DataReceived += (s, e) =>
{
var buffer = new byte[_serialPort.BytesToRead];
_serialPort.Read(buffer, 0, buffer.Length);
_dataQueue.Enqueue(buffer);
DataReceived?.Invoke(buffer);
};
}
private void StartThreads()
{
_readThread = new Thread(ProcessIncomingData);
_writeThread = new Thread(ProcessOutgoingData);
_readThread.Start();
_writeThread.Start();
}
public async Task SendDataAsync(byte[] data)
{
await _serialLock.WaitAsync();
try
{
_writeEvent.Set();
_serialPort.Write(data, 0, data.Length);
}
finally
{
_serialLock.Release();
}
}
private void ProcessIncomingData()
{
while (!_serialPort.IsOpen) Thread.Sleep(100);
while (true)
{
if (_dataQueue.TryDequeue(out var data))
{
// 数据解析逻辑
ParseData(data);
}
Thread.Sleep(10);
}
}
private void ProcessOutgoingData()
{
while (true)
{
_writeEvent.WaitOne();
// 发送队列处理逻辑
}
}
private void ParseData(byte[] data)
{
// 实现具体协议解析
}
public void Dispose()
{
_serialLock.Dispose();
_writeEvent.Dispose();
_serialPort?.Close();
_serialPort?.Dispose();
}
}
三、线程同步机制
1. 双缓冲队列设计
csharp
private ConcurrentQueue<byte[]> _readBuffer = new ConcurrentQueue<byte[]>();
private ConcurrentQueue<byte[]> _processBuffer = new ConcurrentQueue<byte[]>();
// 数据接收线程
void ReceiveThread()
{
while (true)
{
if (_serialPort.BytesToRead > 0)
{
var buffer = new byte[_serialPort.BytesToRead];
_serialPort.Read(buffer, 0, buffer.Length);
_readBuffer.Enqueue(buffer);
}
Thread.Sleep(1);
}
}
// 数据处理线程
void ProcessThread()
{
while (true)
{
if (_readBuffer.TryDequeue(out var data))
{
_processBuffer.Enqueue(ProcessData(data));
}
}
}
2. 异步读写实现
csharp
public async Task<byte[]> ReadAsync(CancellationToken ct)
{
await _serialLock.WaitAsync(ct);
try
{
var buffer = new byte[1024];
int bytesRead = await _serialPort.BaseStream.ReadAsync(buffer, 0, buffer.Length, ct);
Array.Resize(ref buffer, bytesRead);
return buffer;
}
finally
{
_serialLock.Release();
}
}
public async Task WriteAsync(byte[] data, CancellationToken ct)
{
await _serialLock.WaitAsync(ct);
try
{
await _serialPort.BaseStream.WriteAsync(data, 0, data.Length, ct);
}
finally
{
_serialLock.Release();
}
}
四、异常处理
1. 异常捕获框架
csharp
public void SafeWrite(byte[] data)
{
try
{
_serialLock.Wait();
_serialPort.Write(data, 0, data.Length);
}
catch (TimeoutException ex)
{
HandleTimeout();
}
catch (IOException ex)
{
HandleDeviceDisconnect();
}
finally
{
_serialLock.Release();
}
}
2. 自动重连机制
csharp
private void HandleDeviceDisconnect()
{
_serialLock.Wait();
try
{
if (_serialPort.IsOpen) _serialPort.Close();
Thread.Sleep(1000);
ReinitializePort();
}
finally
{
_serialLock.Release();
}
}
private void ReinitializePort()
{
InitializePort(_config.PortName, _config.BaudRate);
StartThreads();
}
参考代码 c#编写串口通讯代码多线程 www.youwenfan.com/contentcsr/111962.html
五、性能优化
1. 内存池管理
csharp
private ObjectPool<byte[]> _bufferPool = new ObjectPool<byte[]>(() => new byte[1024], 10);
byte[] GetBuffer() => _bufferPool.Get();
void ReturnBuffer(byte[] buffer) => _bufferPool.Return(buffer);
2. 批量数据处理
csharp
public void ProcessBatchData(IEnumerable<byte[]> dataArray)
{
Parallel.ForEach(dataArray, data =>
{
var parsed = ParseData(data);
lock (_processedData)
{
_processedData.Add(parsed);
}
});
}
六、完整使用示例
csharp
var manager = new SerialPortManager("COM3", 115200);
// 异步发送数据
await manager.SendDataAsync(Encoding.UTF8.GetBytes("Hello"));
// 接收回调处理
manager.DataReceived += (data) =>
{
var text = Encoding.UTF8.GetString(data);
Console.WriteLine($"Received: {text}");
};
// 后台数据处理
Task.Run(() =>
{
while (true)
{
if (manager.TryDequeueProcessedData(out var data))
{
UpdateUI(data);
}
}
});
七、调试与监控
1. 日志记录
csharp
public void LogCommunication(string message)
{
lock (_logLock)
{
File.AppendAllText("com_log.txt",
$"{DateTime.Now:HH:mm:ss.fff} - {message}{Environment.NewLine}");
}
}
2. 实时状态监控
csharp
public class SerialStatus
{
public int BytesSent { get; private set; }
public int BytesReceived { get; private set; }
public void IncrementSent(int count) => BytesSent += count;
public void IncrementReceived(int count) => BytesReceived += count;
}
八、扩展功能实现
1. 协议解析器
csharp
public class ModbusParser
{
public static Dictionary<byte, ushort> ParseFrame(byte[] data)
{
// 实现Modbus RTU协议解析
return new Dictionary<byte, ushort>();
}
}
2. 加密传输
csharp
public class SecureSerialPort
{
private Aes _aes = Aes.Create();
public byte[] Encrypt(byte[] data)
{
using (var encryptor = _aes.CreateEncryptor())
using (var ms = new MemoryStream())
{
cs.Write(data, 0, data.Length);
return ms.ToArray();
}
}
}
九、最佳实践建议
-
线程模型选择
-
优先使用
Task替代传统Thread -
高频数据采用
BlockingCollection实现生产者-消费者模式
-
-
资源管理规范
csharpusing (var manager = new SerialPortManager()) { // 自动释放资源 } -
性能监控指标
-
串口缓冲区占用率
-
数据处理延迟
-
异常发生频率
-