C# SerialPort 使用详解

总目录


前言

在工业控制、物联网、嵌入式开发等领域,串口通信(Serial Port Communication)是连接串行设备(如条码扫描器、GPS接收器等)与计算机的重要手段。C# 提供了内置的 SerialPort 类,简化了串口开发的流程。本文将详细介绍如何在C#中使用SerialPort类进行串口通信。


一、什么是 SerialPort?

1. 定义

System.IO.Ports.SerialPort 类(简称 SerialPort)是 .NET 框架中用于串口通信的核心类,它提供了对串行端口的访问,允许我们进行数据的读写、配置串口参数以及处理事件等操作。

2. 串行通信简介

串口通信(Serial Communication)是通过单条数据线按顺序传输数据的通信方式,具有接线简单、成本低廉的特点。在工业控制、物联网设备、传感器等领域广泛应用,波特率范围常见为 9600 9600 9600 115200 115200 115200

  • 在工业自动化、嵌入式系统开发等场景中,串口通信(Serial Communication)仍是硬件交互的核心技术之一。
  • 串行通信是一种数据按位顺序传输的通信方式,常用于连接各种串行设备。
  • C# 通过 System.IO.Ports.SerialPort 类为开发者提供了简洁高效的串口操作接口,支持参数配置、数据读写及事件处理等功能。

3. SerialPort核心功能

  • 端口配置参数:波特率、数据位、校验位、停止位等。
  • 数据读写操作:同步或异步发送/接收数据。
  • 事件驱动通信:通过 DataReceived 事件实时响应数据到达。

4. 典型应用场景

  • 工业设备通信
  • 传感器数据采集
  • 嵌入式系统交互

二、常用的属性和方法

1. 常用属性

属性名类型/说明
PortNamestring 串口名称(如 COM1COM3)。
BaudRateint 波特率,表示数据传输速率。
常用的有9600192003840057600以及115200
ParityParity 奇偶校验类型
None无奇偶校验、Even偶检验、Odd奇检验。
DataBitsint 数据位数。
常见数据位为8位,如需要特别设置,还可设置位5位,6位,7位
StopBitsStopBits 停止位数
None 不使用停止位One 1个停止位、Two2个停止位、OnePointFive1.5个停止位)。
HandshakeHandshake 握手协议(如 NoneRequestToSendXOnXOff)。
EncodingEncoding 数据编码方式(如 Encoding.UTF8)。
ReadTimeoutint 读取操作超时时间(毫秒),默认为 InfiniteTimeout
WriteTimeoutint 写入操作超时时间(毫秒),默认为 InfiniteTimeout
IsOpenbool 表示串口是否已打开。
NewLinestring 定义行结束符(如 "\r\n"),用于 ReadLine()WriteLine()
DtrEnablebool 控制数据终端就绪(DTR)信号状态。
RtsEnablebool 控制请求发送(RTS)信号状态。
ReceivedBytesThresholdint 触发 DataReceived 事件的最小字节数。

2. 常用方法

方法名说明
Open()打开串口。
Close()关闭已打开的串口。
Read(byte[] buffer, int offset, int count)从串口读取指定字节数到缓冲区。
ReadByte()读取单个字节(返回 int,范围 0-255,失败返回 -1)。
ReadLine()读取一行数据,直到遇到 NewLine 定义的结束符。
ReadExisting()读取接收缓冲区中所有可用数据(不阻塞)。
Write(string text)写入字符串到串口(自动按 Encoding 编码)。
Write(byte[] buffer, int offset, int count)写入字节数组到串口。
DiscardInBuffer()清空输入缓冲区中的数据。
DiscardOutBuffer()清空输出缓冲区中的数据。

3. 常用事件

事件名说明
DataReceived当接收到数据且字节数达到 ReceivedBytesThreshold 时触发。
ErrorReceived当串口发生错误(如奇偶校验错误)时触发。

4. 其他重要属性(扩展)

属性名类型/说明
BytesToReadint 接收缓冲区中已接收的字节数。
BytesToWriteint 输出缓冲区中待发送的字节数。
ReadBufferSizeint 设置输入缓冲区大小(默认 4096)。
WriteBufferSizeint 设置输出缓冲区大小(默认 2048)。

三、SerialPort 基础

1. 添加命名空间引用

在使用SerialPort类之前,需要先添加对System.IO.Ports命名空间的引用:

using System.IO.Ports;

2. 初始化与参数配置

串口通信的核心是正确配置参数,确保与硬件设备匹配,否则通信失败。

1)方式1:构造函数

using System.IO.Ports;// 创建对象并指定端口名称(如COM3)
SerialPort serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);

2)方式2:属性配置

// 可选:手动设置参数(适用于动态配置)
SerialPort serialPort = new SerialPort();
serialPort.PortName = "COM3";       // 端口号
serialPort.BaudRate = 9600;         // 波特率
serialPort.Parity = Parity.None;    // 校验位
serialPort.DataBits = 8;            // 数据位
serialPort.StopBits = StopBits.One; // 停止位

3. 打开与关闭串口

1)打开串口

在进行数据传输之前,需要打开串行端口:

serialPort.Open(); // 打开串口

优化一下:加上try catch 做异常处理

try 
{if (!serialPort.IsOpen){serialPort.Open();Console.WriteLine("端口已打开");}
}
catch (Exception ex)
{Console.WriteLine($"打开失败:{ex.Message}");
}

2)关闭串口

数据传输完成后,应及时关闭串行端口。务必在程序退出前调用Close

serialPort.Close(); // 关闭端口

优化一下:加上try catch 做异常处理

try 
{if (serialPort.IsOpen){// 关闭端口serialPort.Close();Console.WriteLine("端口已关闭");// 销毁serialPort对象serialPort.Dispose();}
}
catch (Exception ex)
{Console.WriteLine($"关闭失败:{ex.Message}");
}

4. 读取和写入数据

1)写入数据

▶ 写入字符串数据
  • 使用Write()方法:将指定的字符串写入串行端口。
  • 使用WriteLine方法:将指定的字符串和 SerialPort.NewLine 值写入串行端口。
serialPort.Write("Hello, Serial!");// 自动添加换行符:发送字符串并添加换行符(WriteLine)
serialPort.WriteLine("Hello, Serial Port!");
▶ 写入字节流(字节数组)数据
// 发送字节数组
byte[] data = Encoding.UTF8.GetBytes("Test Data");
serialPort.Write(data, 0, data.Length);byte[] data = { 0x01, 0xFF, 0xAB }; // 十六进制数据
serialPort.Write(data, 0, data.Length); // 发送字节

2)读取数据

可以通过Read()ReadLine()等方法从串口读取数据。

// 读取指定字节数
byte[] buffer = new byte[1024];
int bytesRead = serialPort.Read(buffer, 0, buffer.Length);
string received = Encoding.UTF8.GetString(buffer, 0, bytesRead);// 读取一行数据(依赖 NewLine 配置)
string line = serialPort.ReadLine();

5. 处理数据接收事件

通过 DataReceived 事件实时接收串口数据。当有数据到达时,DataReceived事件会被触发。可以通过注册该事件来实时处理接收到的数据:

1)使用方式1

// 注册 DataReceived 事件
serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{SerialPort sp = (SerialPort)sender;string received = sp.ReadExisting(); // 读取所有可用数据Console.WriteLine($"Received: {received}");
}

2)使用方式2

serialPort.DataReceived += SerialPort_DataReceived;
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{//首先实例化一个字节数组// 字节数组的大小:通过BytesToRead 属性,获取得到缓冲区中数据的字节数byte[] buffer = new byte[serialPort.BytesToRead];//再通过 Read() 方法 读取缓存区内全部数据,并将数据写入字节数组中serialPort.Read(buffer, 0, buffer.Length);// 解码string received = Encoding.ASCII.GetString(buffer); Console.WriteLine(received);
}

3)使用方式3

serialPort.DataReceived += (sender, e) => 
{if (e.EventType == SerialData.Chars){byte[] buffer = new byte[serialPort.BytesToRead];serialPort.Read(buffer, 0, buffer.Length);string data = Encoding.ASCII.GetString(buffer);Console.WriteLine($"收到数据:{data}");}
};

以上三种方式,基本原理一致,只是部分的读取数据方式和事件定义的方式稍有不同而已。

6. 完整示例

示例1:简单示例

using System;
using System.IO.Ports;
using System.Windows.Forms;public class SerialPortDemo
{//配置并创建SerialPort实例private SerialPort sp = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);public void Start(){try{// 注册数据接收事件sp.DataReceived += DataReceivedHandler;// 打开串口sp.Open();//写入数据sp.WriteLine("Start Communication");}catch (Exception ex){MessageBox.Show($"初始化失败:{ex.Message}");}}// 接收数据private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e){// 读取数据string data = sp.ReadExisting();Console.WriteLine($"实时数据:{data}");}// 关闭端口public void Stop() => sp.Close();
}

示例2:WinForm 示例

以下是一个完整的示例,展示如何在C#中使用SerialPort类进行串口通信。

using System;
using System.IO.Ports;
using System.Windows.Forms;namespace SerialPortExample
{public partial class MainForm : Form{private SerialPort serialPort;public MainForm(){InitializeComponent();InitializeSerialPort();}private void InitializeSerialPort(){serialPort = new SerialPort();serialPort.PortName = "COM1";serialPort.BaudRate = 9600;serialPort.Parity = Parity.None;serialPort.DataBits = 8;serialPort.StopBits = StopBits.One;serialPort.Handshake = Handshake.None;serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);}private void btnOpen_Click(object sender, EventArgs e){try{if (!serialPort.IsOpen){serialPort.Open();MessageBox.Show("串口已打开");}}catch (Exception ex){MessageBox.Show("打开串口时出错: " + ex.Message);}}private void btnSend_Click(object sender, EventArgs e){if (serialPort.IsOpen){string message = txtSend.Text;serialPort.WriteLine(message);txtReceive.AppendText("发送: " + message + Environment.NewLine);}else{MessageBox.Show("请先打开串口");}}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){SerialPort sp = (SerialPort)sender;string indata = sp.ReadExisting();this.Invoke(new Action(() =>{txtReceive.AppendText("接收: " + indata);}));}private void btnClose_Click(object sender, EventArgs e){if (serialPort.IsOpen){serialPort.Close();MessageBox.Show("串口已关闭");}}}
}

示例3:扫码枪数据接收

SerialPort port = new("COM3", 115200, Parity.None, 8, StopBits.One);
port.DataReceived += (s, e) => 
{byte[] barcode = new byte[port.BytesToRead];port.Read(barcode, 0, barcode.Length);// 解析扫码枪数据(通常以回车结尾)if (barcode.Last() == 0x0D) {string code = Encoding.ASCII.GetString(barcode);ProcessBarcode(code);}
};

四、SerialPort 进阶

1. 高级参数配置

1)配置超时时间

防止长时间阻塞(单位:毫秒)。

// 设置读取超时为 1000ms
serialPort.ReadTimeout = 1000;
// 设置写入超时
serialPort.WriteTimeout = 500;

2)缓冲区设置

ReceivedBytesThreshold:指定触发 DataReceived 事件的字节阈值,即触发 DataReceived 事件的最小字节数。

serialPort.ReceivedBytesThreshold = 2;	//默认值 为 1

3)其余参数配置

sp.Encoding = Encoding.ASCII; 	// 编码格式
sp.NewLine = "\r\n";       		// 换行符定义

2. 获取所有可用 COM 端口

可以通过SerialPort.GetPortNames()方法获取系统中所有可用的串行端口名称:

// 获取所有可用 COM 端口
string[] ports = SerialPort.GetPortNames();
foreach (var port in ports)
{Console.WriteLine(port);
}

3. ErrorReceived事件

当串行通信中发生错误(如帧错误/缓冲区溢出)时,ErrorReceived事件会被触发:

serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
private static void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{if ((e.EventType & SerialError.Frame) == SerialError.Frame){Console.WriteLine("Frame error detected.");}if ((e.EventType & SerialError.Overrun) == SerialError.Overrun){Console.WriteLine("Overrun error detected.");}if ((e.EventType & SerialError.RXParity) == SerialError.RXParity){Console.WriteLine("Parity error detected.");}
}
sp.ErrorReceived += (sender, e) => 
{Console.WriteLine($"错误类型:{e.EventType}");
};

4. 异常处理

使用try-catch块捕获和处理可能的异常,确保程序的稳定性:

try
{serialPort.Open();serialPort.WriteLine("Hello, Serial Port!");serialPort.Close();
}
catch (Exception ex)
{Console.WriteLine("Error: " + ex.Message);
}
// 常见异常类型
try 
{// 串口操作代码
}
catch (UnauthorizedAccessException ex)
{Console.WriteLine("端口访问被拒绝");
}
catch (TimeoutException ex) 
{Console.WriteLine("操作超时");
}
catch (IOException ex)
{Console.WriteLine("I/O错误");
}

5. 跨线程处理

为了能够实时响应串口接收到的数据,可以使用DataReceived事件。需要注意的是,该事件在单独的线程中触发,若要更新UI控件,涉及到跨线程,需要使用Invoke方法。

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{SerialPort sp = (SerialPort)sender;string received = sp.ReadExisting();// 数据接收后,通过委托更新UI(假设在 WinForms 中更新TextBox)this.Invoke(new Action(() =>{textBox.Text += received ;}));
}

6. 多线程处理

推荐使用生产者-消费者模式:

BlockingCollection<string> dataQueue = new BlockingCollection<string>();// 生产者线程
void DataReceivedHandler(...)
{dataQueue.Add(receivedData);
}// 消费者线程
Task.Run(() => 
{foreach (var data in dataQueue.GetConsumingEnumerable()){// 处理数据}
});

五、常见问题与注意事项

1. 注意事项

  • 参数一致性:确保双方设备的波特率、数据位、停止位、校验位一致。
  • 权限问题:在访问串口时,需要确保程序有相应的权限,否则可能会抛出异常。
  • 线程安全:在DataReceived事件中处理数据时,由于它是在单独的线程中触发的,若要更新UI控件,必须使用Invoke方法来确保线程安全
  • 异常处理:使用 try-catch 处理 Open()Read()Write() 可能抛出的异常。
  • 缓冲区管理:通过 DiscardInBufferDiscardOutBuffer 清空缓冲区,避免数据残留。
    • 避免重复打开同一端口,关闭前调用 sp.DiscardInBuffer() 清空缓存。
  • 硬件流控制
    在高速传输场景中启用 Handshake.RequestToSend,避免数据丢失。

2. 常见问题

  • 端口无法打开
    • 检查设备是否占用(如其他程序已连接)
    • 确认串口号是否正确(虚拟串口可能动态变化)
    • 异常处理:try...catch(IOException)捕获端口不存在错误
  • 数据接收不完整
    • 使用BytesToRead确保读取全部缓存数据
    • 添加延迟(如Thread.Sleep(50))等待完整帧
    • 硬件延迟:部分设备发送数据有间隔,需调整时序
  • 数据乱码
    • 发送/接收端波特率必须一致,否则数据乱码。
  • 字符编码问题
    • 若接收中文字符乱码,需设置:
    • serialPort.Encoding = Encoding.GetEncoding("GB2312")
    • serialPort.Encoding = Encoding.UTF8;

六、扩展

1. 跨平台方案(RJCP.SerialPortStream)

对于需要跨平台(Linux/macOS)的场景,推荐使用 RJCP.SerialPortStream 库(通过 NuGet 安装 RJCP.SerialPortStream):

using RJCP.IO.Ports;SerialPortStream serialPort = new SerialPortStream("COM3");
serialPort.BaudRate = 9600;
serialPort.Open();// 事件处理与读写方式与 SerialPort 类似
serialPort.DataReceived += (sender, e) => 
{byte[] data = new byte[serialPort.BytesToRead];serialPort.Read(data, 0, data.Length);Console.WriteLine(Encoding.UTF8.GetString(data));
};

2. 编码

使用串口通信的时候,会涉及到数据的编码格式,如果我们使用ASCII编码格式,但是接收的时候采用的是其他的编码格式,可能就会导致数据解析错误,因此在一些特定场景下我们需要规定好发送和接收数据的编码格式,这个时候就需要用到System.Text.Encoding 类中的编码解码的功能。
详见:C# System.Text.Encoding 使用详解

3. 清空缓冲区的方法

关于 DiscardInBuffer / DiscardOutBuffer 的使用,详见:C# SerialPort 类中清空缓存区的方法。

4. Handshake 设置

常用握手协议

  • Handshake.None:无握手。
  • Handshake.RequestToSend:RTS/CTS(请求发送/清除发送)。
  • Handshake.XOnXOff:软件流控制(XON/XOFF 字符)。
serialPort.Handshake = Handshake.RequestToSend;

详见:C# SerialPort 类中 Handshake 属性的作用

结语

回到目录页:C# 上位机知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料:

  • 官方文档:SerialPort Class

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/73436.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3D点云的深度学习网络分类(按照作用分类)

1. 3D目标检测&#xff08;Object Detection&#xff09; 用于在点云中识别和定位目标&#xff0c;输出3D边界框&#xff08;Bounding Box&#xff09;。 &#x1f539; 方法类别&#xff1a; 单阶段&#xff08;Single-stage&#xff09;&#xff1a;直接预测3D目标位置&am…

LabVIEW 与 PLC 通讯的常见方式

在工业自动化和数据采集系统中&#xff0c;PLC&#xff08;可编程逻辑控制器&#xff09; 广泛用于控制和监测各种设备&#xff0c;而 LabVIEW 作为强大的图形化编程工具&#xff0c;常用于上位机数据处理和可视化。为了实现 LabVIEW 与 PLC 的高效通讯&#xff0c;常见的方法包…

2025 polarctf春季个人挑战赛web方向wp

来个弹窗 先用最基础的xss弹窗试一下 <script>alert("xss")</script>没有内容&#xff0c;猜测过滤了script&#xff0c;双写绕过一下 <scrscriptipt>alert("xss")</scscriptript>background 查看网页源代码 查看一下js文件 类…

【Ai】--- 可视化 DeepSeek-r1 接入 Open WebUI(超详细)

在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。【Ai】--- 可视化 DeepSeek-r1 接入 Open WebUI(超详细) 开发环境一、前情提要:你…

7.1-7.2考研408数据结构查找算法核心知识点深度解析

考研408数据结构查找算法核心知识点深度解析 一、查找基本概念 1.1 核心定义与易错点 查找表与关键字 易错点:混淆静态查找表(仅查询)与动态查找表(含插入/删除操作)的应用场景。例如哈希表属于动态查找结构,而分块查找适用于静态数据。难点:理解平均查找长度(ASL)的…

Redis--redis客户端

目录 一、引言 二、数据库管理命令 三、redis客户端 四、Java客户端使用Redis 五、相关命令使用 1.get&#xff0c;set 2.exists&#xff0c;del 3.keys 4.expire&#xff0c;ttl 六、总结 一、引言 在之前学了redis相关类型命令之后&#xff0c;本篇文章&#xff0c;…

SpringBoot3.0不建议使用spring.factories,使用AutoConfiguration.imports新的自动配置方案

文章目录 一、写在前面二、使用imports文件1、使用2、示例比对3、完整示例 参考资料 一、写在前面 spring.factories是一个位于META-INF/目录下的配置文件&#xff0c;它基于Java的SPI(Service Provider Interface)机制的变种实现。 这个文件的主要功能是允许开发者声明接口的…

鸿蒙特效教程10-卡片展开/收起效果

鸿蒙特效教程10-卡片展开/收起效果 在移动应用开发中&#xff0c;卡片是一种常见且实用的UI元素&#xff0c;能够将信息以紧凑且易于理解的方式呈现给用户。 本教程将详细讲解如何在HarmonyOS中实现卡片的展开/收起效果&#xff0c;通过这个实例&#xff0c;你将掌握ArkUI中状…

hn航空app hnairSign unidbg 整合Springboot

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向分析 学习unidbg补环境。先弄一个…

奇怪的异形选项卡样式、弧形边框选项卡

<template><div :class"$options.name"><div class"tab">默认选项卡</div><div class"tab" active>选中选项卡</div><el-divider /><el-tabs v-model"tabActiveName" tab-click"(t…

特殊行车记录仪DAT视频丢失的恢复方法

行车记录仪是一种常见的车载记录仪&#xff0c;和常见的“小巧玲珑”的行车记录仪不同&#xff0c;一些特种车辆使用的记录仪的外观可以用“笨重”来形容。下边我们来看看特种车载行车记录仪删除文件后的恢复方法。 故障存储: 120GB存储设备/文件系统:exFAT /簇大小:128KB 故…

UE5小石子阴影在非常近距离才显示的问题

Unreal中采用LandscapeGrass生成的地形&#xff0c;在MovieRenderQueue中渲染时阴影显示距离有问题&#xff0c;在很近的时候才会有影子&#xff0c;怎么解决&#xff1f; 地面上通过grass生成的小石子的阴影只能在很近的时候才能显示出来&#xff0c;需要如下调整 r.Shadow.R…

零基础上手Python数据分析 (9):DataFrame 数据读取与写入 - 让数据自由穿梭

回顾一下,上篇博客我们学习了 Pandas 的核心数据结构 Series 和 DataFrame。 DataFrame 作为 Pandas 的 “王牌” 数据结构,是进行数据分析的基石。 但 DataFrame 的强大功能,还需要建立在 数据输入 (Input) 和 数据输出 (Output) 的基础上。 数据从哪里来? 分析结果又如何…

【商城实战(65)】退换货流程全解析:从前端到后端的技术实现

【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配,乃至运营推广策略,102 章内容层层递进。无论是想…

SQL Server 2022 安装问题

一、安装与配置问题 1. SQL Server 2022 安装失败怎么办&#xff1f; 常见原因&#xff1a; 硬件或操作系统不满足最低要求&#xff08;如内存、磁盘空间不足&#xff09;。未关闭防火墙或杀毒软件。之前版本的 SQL Server 残留文件未清理。 解决方案&#xff1a; 确保硬件配…

解锁 AWX+Ansible 自动化运维新体验:快速部署实战

Ansible 和 AWX 是自动化运维领域的强大工具组合。Ansible 是一个简单高效的 IT 自动化工具&#xff0c;而 AWX 则是 Ansible 的开源 Web 管理平台&#xff0c;提供图形化界面来管理 Ansible 任务。本指南将带你一步步在 Ubuntu 22.04 上安装 Ansible 和 AWX&#xff0c;使用 M…

【xiaozhi赎回之路-2:语音可以自己配置就是用GPT本地API】

固件作用 打通了网络和硬件的沟通 修改固件实现【改变连接到小智服务器的】 回答逻辑LLM自定义 自定义了Coze&#xff08;比较高级&#xff0c;自定义程度比较高&#xff0c;包括知识库&#xff0c;虚拟脚色-恋人-雅思老师-娃娃玩具{可能需要使用显卡对开源模型进行微调-产…

Springboot 学习 之 Shardingsphere 按照日期水平分表(二)

文章目录 业务场景依赖配置特别注意优劣参考资料 业务场景 在 报表 等 大数据量 且需要 按照日期显示 的业务场景下&#xff0c;按照 日期水平分表 是一个不错的选择 依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-b…

(UI自动化测试web端)第二篇:元素定位的方法_xpath扩展(工作当中用的比较多)

看代码里的【driver.find_element_by_xpath( )】()里的路径怎么写&#xff1f; xpath元素定位有多种写法&#xff0c;那我们现在说的就是在元素定位时&#xff0c;根据网页的实际情况来选择适合的xpath元素定位的写法。信我 &#xff0c;你真正工作当中每个都有用的&#xff01…

[已解决]服务器CPU突然飙高98%----Java程序OOM问题 (2024.9.5)

目录 问题描述问题排查问题解决参考资料 问题描述 业主单位服务器自8月29日晚上21:00起CPU突然飙高至98%&#xff0c;内存爆满&#xff0c;一直到9月5日&#xff1a; 问题排查 ①执行 top 命令查看Java进程PID top②执行top -Hp PID 命令查看具体的线程情况 top -Hp 3058输入上…