基于C#实现多线程串口通信

一、核心架构设计

主线程
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();
        }
    }
}

九、最佳实践建议

  1. 线程模型选择

    • 优先使用Task替代传统Thread

    • 高频数据采用BlockingCollection实现生产者-消费者模式

  2. 资源管理规范

    csharp 复制代码
    using (var manager = new SerialPortManager())
    {
        // 自动释放资源
    }
  3. 性能监控指标

    • 串口缓冲区占用率

    • 数据处理延迟

    • 异常发生频率

相关推荐
安科士andxe9 小时前
深入解析|安科士1.25G CWDM SFP光模块核心技术,破解中长距离传输痛点
服务器·网络·5g
YJlio12 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
CTRA王大大12 小时前
【网络】FRP实战之frpc全套配置 - fnos飞牛os内网穿透(全网最通俗易懂)
网络
testpassportcn13 小时前
AWS DOP-C02 認證完整解析|AWS DevOps Engineer Professional 考試
网络·学习·改行学it
通信大师13 小时前
深度解析PCC策略计费控制:核心网产品与应用价值
运维·服务器·网络·5g
Tony Bai14 小时前
告别 Flaky Tests:Go 官方拟引入 testing/nettest,重塑内存网络测试标准
开发语言·网络·后端·golang·php
消失的旧时光-194315 小时前
从 0 开始理解 RPC —— 后端工程师扫盲版
网络·网络协议·rpc
游乐码15 小时前
c#变长关键字和参数默认值
学习·c#
叫我龙翔16 小时前
【计网】从零开始掌握序列化 --- JSON实现协议 + 设计 传输\会话\应用 三层结构
服务器·网络·c++·json
全栈小516 小时前
【C#】合理使用DeepSeek相关AI应用为我们提供强有力的开发工具,在.net core 6.0框架下使用JsonNode动态解析json字符串,如何正确使用单问号和双问号做好空值处理
人工智能·c#·json·.netcore·deepseek