基于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. 性能监控指标

    • 串口缓冲区占用率

    • 数据处理延迟

    • 异常发生频率

相关推荐
SilentSamsara19 分钟前
TLS/HTTPS 实战:证书链、握手与生产配置
网络·数据库·网络协议·http·https
U盘失踪了20 分钟前
URL 统一资源定位符详解
网络
爱学习的小囧21 分钟前
ESXi/vCenter 批量开关虚拟机完整教程 | PowerCLI 一键 + 原生脚本循环,新手也能落地
运维·网络·数据库·esxi
bbq粉刷匠29 分钟前
网络基础概念
网络·tcp/ip·计算机网络
路溪非溪1 小时前
Wireshark抓取以太网MAC帧并进行分析
linux·网络·驱动开发·wireshark
阿正的梦工坊1 小时前
JavaScript 函数组合(Compose & Pipe)详解
开发语言·javascript·网络
heimeiyingwang1 小时前
【架构实战】Docker容器网络模型详解
网络·docker·架构
NQBJT2 小时前
[特殊字符] VS Code + Markdown 从入门到精通:写论文、技术文档的超实用指南
开发语言·vscode·c#·markdown
小江的记录本2 小时前
【网络安全】《网络安全与数据安全核心知识体系》(包括数据脱敏、数据加密、隐私合规、等保2.0)
java·网络·后端·python·算法·安全·web安全
@insist1232 小时前
网络工程师-动态路由协议(二):BGP 协议与路由引入技术详解
运维·网络·网络工程师·软考·软件水平考试