坪地网站建设价格深圳龙华建网站公司
- 作者: 五速梦信息网
- 时间: 2026年03月21日 10:14
当前位置: 首页 > news >正文
坪地网站建设价格,深圳龙华建网站公司,怎样做招嫖网站,建造免费网站最近使用WPF开发串口助手时#xff0c;遇到一个很奇怪的问题#xff0c;无论是主线程、异步还是多线程#xff0c;当串口接收速度达到0.016s一次以上#xff0c;就会发生字符串缺失问题并且很卡。而0.016s就一切如常#xff0c;仿佛0.015s与0.016s是天堑之隔。 同一份代码… 最近使用WPF开发串口助手时遇到一个很奇怪的问题无论是主线程、异步还是多线程当串口接收速度达到0.016s一次以上就会发生字符串缺失问题并且很卡。而0.016s就一切如常仿佛0.015s与0.016s是天堑之隔。 同一份代码放在多线程主线程或异步环境中 由于是在测试尝试过用索引下标的方式遍历数组 其中allData的定义为 Liststring allData new Liststring(); if (allData.Count 0){RecvBuffer.Clear();StringBuilder sb new StringBuilder();sb.Append(DateTime.Now);sb.Append();Application.Current.Dispatcher.Invoke(() {for (int i 0; i allData.Count; i){RecvBuffer.Append(sb);RecvBuffer.Append(allData[i]);}TextEditor?.AppendText(RecvBuffer.ToString());});} 0.016s一次接收 日期可以正常打印下来而且打印的速度很快整体显示很流畅 0.015s一次接收 虽然串口发送脚本的速度只提高了一点点但是日期时间几乎不打印只有零星几个有而且整个显示非常卡 按理来说这两个速度差别应该不大不至于产生这种差别后来又相继测试了多线程、异步、主线程的全速打印直接放进while死循环里拟定的固定字符串 但都可以正常显示日期时间。 于是只能怀疑到字符串本身的问题了由于此前本人是学C/C的对C#的字符串原理还不甚了解大概知道C#的字符串中的“\0”并非作为字符串的结尾。但此时的打印结果却让我对C#的字符串拼接原理产生了深深的困惑。 根据前面的全速打印等测试情况如果把硬编码的字符串或者数字塞进StringBuilder是没有问题的所以想知道是不是字符串本身的问题于是我把allData里的数据先转为数字再直接拼接字符串 if (allData.Count 0){RecvBuffer.Clear();StringBuilder sb new StringBuilder();sb.Append(DateTime.Now);sb.Append();Application.Current.Dispatcher.Invoke(() {for (int i 0; i allData.Count; i){RecvBuffer.Append(sb);var value float.TryParse(allData[i], out var val);RecvBuffer.Append(\({val}\n);}TextEditor?.AppendText(RecvBuffer.ToString());});} 虽然变得极其卡但可以正常显示日期时间了 然而把字符串中的\0去掉之后并没有达到我的预期依旧会很卡且没有日期时间 查了许多资料也问了AI很长时间前前后后花了好几天最终未能揭开其中的原理 不知道是队列的原因还是SerialPort中Read与ReadExisting的区别或是字符串与字节数组的原因亦或是多次接收的数据变为合并为一个数据总之经过了下面变换可用了而且打印效率肉眼可见地提升不再卡顿了。 // 原代码// 在OnDataReceived中private void OnDataReceived(object? sender, SerialDataReceivedEventArgs e){if (sender is SerialPort sp){//ReceiveBytes sp.BytesToRead;//ReceiveNum;string data sp.ReadExisting();_receiveQueue.Enqueue(data); // 将接收到的数据放入接收队列//_queueSemaphore.Release(); // 信号量释放通知有新数据_resetEvent.Set(); // 通知读取任务开始处理数据}}// 读取任务private void ReadTask(){while (_isRunning){_resetEvent.WaitOne(); // 等待数据接收事件if (!_isRunning)break;Liststring allData new Liststring();while (true){if (!(_receiveQueue.TryDequeue(out var data)))break;allData.Add(data);if (allData.Count 10240)break;Thread.Sleep(10); // 适当休眠避免过度占用CPU}if (allData.Count 0){Application.Current.Dispatcher.Invoke(() {foreach (var item in allData){TextEditor?.AppendText(\)[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {item});}});}}} // 改进后private void OnDataReceived(object? sender, SerialDataReceivedEventArgs e){if (sender is SerialPort sp){//ReceiveBytes sp.BytesToRead;//ReceiveNum;//string data sp.ReadExisting();//_receiveQueue.Enqueue(data); // 将接收到的数据放入接收队列//_queueSemaphore.Release(); // 信号量释放通知有新数据_resetEvent.Set(); // 通知读取任务开始处理数据}}public async void ReadTask(){const int MaxDataSize 512;const int BatchSize 1024; // 批量读取大小var allData new Listbyte();while (true){_resetEvent.WaitOne(); // 等待数据接收事件try{while (allData.Count MaxDataSize _serialPort.BytesToRead 0){var bytesToRead Math.Min(_serialPort.BytesToRead, BatchSize);var buffer new byte[bytesToRead];_serialPort.Read(buffer, 0, bytesToRead);allData.AddRange(buffer);if (allData.Count MaxDataSize) break;await Task.Delay(10); // 防止CPU占用过高使用异步延迟}}catch{// 处理异常allData.Clear();continue;}if (allData.Count 0){await LogMessageAsync(_serialPort.Encoding.GetString(allData.ToArray()), DateTime.Now.ToString());allData.Clear(); // 清空数据列表}}}private async Task LogMessageAsync(string inputData, string timestamp){// 使用StringBuilder提高效率var sb new StringBuilder();sb.Append(\([{timestamp}] );// 使用正则表达式替换换行符并添加时间戳var logEntry Regex.Replace(inputData, (\r\n|\r|\n), \)\r\n{timestamp} );sb.Append(logEntry);// 异步更新UIawait Application.Current.Dispatcher.InvokeAsync(() {TextEditor?.AppendText(sb.ToString());});} 出于时间考量不再深究于此留下痕迹。 2024.11.28 淦用这个可以流畅打印的函数试了之后发现一个不对劲的地方那就是接收字节数过大测了一下发现Python脚本发送数据的真实速度是16359.5次/s即0.00006s发送一次数据 千算万算没想到是python脚本的问题不过这倒也解决了“0.015s”与0.016s一次差距悬殊的原因并且也找到了能高性能显示的方案。真淦 下面是罪魁祸首 import asyncio import math import randomimport serial import serial_asyncioclass VirtualSerialServer(asyncio.Protocol):def init(self, baudrate115200, interval0.1, frequency1.0, amplitude1.0, offset0.0):self.transport Noneself.baudrate baudrateself.interval intervalself.frequency frequency # 正弦波频率Hzself.amplitude amplitude # 正弦波振幅self.offset offset # 正弦波偏移量self.time 0.0 # 当前时间def connection_made(self, transport):self.transport transportprint(fVirtual Serial Port connected with baudrate {self.baudrate})asyncio.create_task(self.send_data_periodically())# def data_received(self, data):# print(fReceived: {data.decode()})# # 回显接收到的数据# self.transport.write(data)async def send_data_periodically(self):value 0while True:# 生成100以内的随机整数# value random.randint(0, 100)# 将整数转换为字符串格式value 1data_to_send f{value}\n.encode(utf-8)self.transport.write(data_to_send)# 打印数据# print(fSent: {value})await asyncio.sleep(self.interval)async def main():# 固定波特率和时间间隔baudrate 115200interval 0.015 # 发送间隔秒# 使用实际的虚拟串口号例如 COM15port COM15loop asyncio.get_running_loop()try:server await serial_asyncio.create_serial_connection(loop, lambda: VirtualSerialServer(baudrate, interval), urlport, baudratebaudrate)except serial.serialutil.SerialException as e:print(fError opening serial port {port}: {e})returnawait asyncio.Event().wait() # 保持程序运行if name main:try:asyncio.run(main())except KeyboardInterrupt:print(程序已终止。)经过一些测试发现在异步情况下Python的定时执行容易出现很奇葩的问题在我的例子中0.015s就是那个极限0.016s及其以上却是正常的。 下面是经过改正且可以正常使用的代码 import time import serialclass VirtualSerialServer:def init(self, interval0.015):self.interval intervalself.last_send_time None # 记录上次发送时间self.value 0 # 初始化发送的数据值def start(self, port, baudrate):try:with serial.Serial(port, baudrate) as ser:print(fVirtual Serial Port connected with interval {self.interval})while True:current_time time.perf_counter()if self.last_send_time is not None:actual_interval current_time - self.last_send_timeprint(fSent: {self.value}, Actual interval: {actual_interval:.6f} seconds) # 打印实际间隔# 发送数据self.value 1data_to_send f{self.value}\n.encode(utf-8)ser.write(data_to_send)# 更新最后一次发送时间self.last_send_time current_time# 等待直到下一个发送时间点next_send_time self.last_send_time self.intervalwhile time.perf_counter() next_send_time:pass # 空循环等待直到达到下一个发送时间点except serial.SerialException as e:print(fError opening serial port {port}: {e})if name main:interval 0.012 # 发送间隔秒port COM15 # 使用实际的虚拟串口号baudrate 115200 # 固定波特率server VirtualSerialServer(intervalinterval)try:server.start(port, baudrate)except KeyboardInterrupt:print(程序已终止。)
- 上一篇: 评论网站建设网页代码查看
- 下一篇: 坪地网站建设市场微信小程序开发制作平台
相关文章
-
评论网站建设网页代码查看
评论网站建设网页代码查看
- 技术栈
- 2026年03月21日
-
评论回复网站怎么做的设计公司起名常用字
评论回复网站怎么做的设计公司起名常用字
- 技术栈
- 2026年03月21日
-
平阴市住房和城乡建设局网站马鞍山什么房产网站做的好
平阴市住房和城乡建设局网站马鞍山什么房产网站做的好
- 技术栈
- 2026年03月21日
-
坪地网站建设市场微信小程序开发制作平台
坪地网站建设市场微信小程序开发制作平台
- 技术栈
- 2026年03月21日
-
坪地做网站深圳社保网上服务平台
坪地做网站深圳社保网上服务平台
- 技术栈
- 2026年03月21日
-
坪山网站建设wordpress 随机阅读数
坪山网站建设wordpress 随机阅读数
- 技术栈
- 2026年03月21日






