使用Delphi做蓝牙BLE开发的一个问题

概念

Delphi 的 BLE 开发,拖一个 TBlueToothLe 到界面上,使用这个控件,就可以进行 BLE 的开发,比如去连接一个蓝牙手环。

Delphi 自带的 Demo 里面,有一个 BLEScanner 程序,可以作为开发的起点。

问题

上述程序,如果在 Windows 底下执行,扫描出设备后,如果鼠标点击某个设备,可能会界面冻结,程序没有响应。看任务管理区,确实程序没有了响应,死机了。

原因分析

鼠标点击,是执行对选中设备的服务的扫描。然后,当发现该设备的服务后,触发了 TBluetoothLE 的 OnServicesDiscovered 事件。在该事件中,循环读取该设备的多个服务,然后对某一个服务,循环读取它的 Character 的名字。死机正是循环读取 Character 那里。

为什么会死机,我不知道。但发现一个解决办法,代码如下:

procedure TForm6.BluetoothLE1ServicesDiscovered(const Sender: TObject; const AServiceList: TBluetoothGattServiceList);
varServiceIndex: Integer;Service: TBluetoothGattService;CharacteristicIndex: Integer;Characteristic: TBluetoothGattCharacteristic;
begin//以下代码如果不包到 TTask.Run 里面(原本的代码没有),在 WINDOWS 底下,执行到 for //CharacteristicIndex := 0 to Service.Characteristics.Count 会界面冻结,而且单步跟踪也停止 //了,没有往下执行。TTask.Run(  procedurevarServiceIndex: Integer;CharacteristicIndex: Integer;beginif AServiceList.Count > 0 thenbeginfor ServiceIndex := 0 to AServiceList.Count - 1 dobeginService := AServiceList[ServiceIndex];TThread.Synchronize(nil,procedurebeginListbox2.Items.Add((ServiceIndex + 1).ToString + ' - ' + Service.UUIDName + ' - ' + Service.UUID.ToString);end);//以下代码会导致死机,如果断点跟踪,直接就是停在 for 这一行,不会继续往下执行。for CharacteristicIndex := 0 to Service.Characteristics.Count - 1 dobeginCharacteristic := Service.Characteristics[CharacteristicIndex];TThread.Synchronize(nil,procedurebeginListbox2.Items.Add('    - ' + Characteristic.UUIDName + ' - ' + Characteristic.UUID.ToString);end);end;end;endelseTThread.Synchronize(nil,procedurebeginListbox2.Items.Add('- Access not allowed or no service available');end);end);//Listbox1.Enabled := True;
end;

代码解释

上述代码里面,TTask.Run 是我增加的。TThread.Synchronize 也是我增加的。去掉 TTask.Run 和 TThread.Synchronize 剩下的代码就是 Delphi 自带的 Demo 原本的代码。

首先,把原本的代码放进 TTask.Run 里面,就是把这些代码,放进了一个线程去执行。而不是让原本引发 OnServicesDiscovered 这个事件的线程去执行。可能原因:引发 OnServicesDiscovered 的这个线程,不能执行太多耗时的任务。

代码在线程里面执行,当需要往界面控件写数据时,比如 Listbox2.Items.Add 这样的代码,就需要做一个线程同步。因此加上  TThread.Synchronize。

我的开发环境

不同的环境下,可能现象不同。因此,这里要提一下我的开发环境:

Delphi 11 社区版;

Windows 11 家庭版;

编译运行的目标程序是 Win32 版本。

没有测试这个 Demo 在安卓底下是否会有上述问题。但我相信在安卓下,同样加上 TTask.Run 也会更好。

Demo 程序的位置

这里提到的 Demo,安装了 Delphi 以后,如果是默认安装,这个 Demo 程序在:

C:\Users\Public\Documents\Embarcadero\Studio\22.0\Samples\Object Pascal\Multi-Device Samples\Device Sensors and Services\Bluetooth\BLEScanner

结论

使用 Delphi 开发 BLE 程序,比如做一个手环 APP,是没有问题的。但是需要留意,在 TBluetoothLE 这个控件的很多事件里面,最好不要执行太多的代码。如果有复杂的业务逻辑,最好放到单独的线程里面去执行,事件方法里面,仅仅是启动对应的线程。

对于 Delphi 来说,新增加的 TTask.Run 让我们把一大堆代码丢进线程执行,代码写法相对以前必须搞一个线程类,简单了很多。

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

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

相关文章

【解密】记一次辽宁省某综合实践教学管理平台加解密算法分析

最近接到需求,于是准备弄一下,发现对方整个流程是:先加密在请求,请求得到的数据再进行拼接加密,不过花了2个小时还是完成了解密 哈哈 找到请求发现请求数据加密 在启动器里面发现登录方法 打印出各个关键变量数据 …

PyTorch 2-深度学习-模块

PyTorch 2-深度学习-模块 一: pytorch1> pytorch 介绍2> pytorch 作用3> pytorch 优点4> pytorch 流程二:pytorch 模块1> torch.Tensor 模块2> torch.nn模块3> torch.nn.function模块4> torch.random模块5> torch.onnx模块6> torch.sparse模块7…

QT之嵌入外部第三方软件到本窗体中

一、前言 使用QT开发,有时需要调用一些外部程序,但是单独打开一个外部窗口有的场合很不合适,最好是嵌入到开发的QT程序界面中。还有就是自己开发的n个程序,一个主程序托n个子程序,为了方便管理将各个程序独立&#xf…

【TS】typescript 获取函数入参类型、返回值类型、promise返回值类型

文章目录 1. 准备工作2. 获取函数入参的类型3. 获取函数返回值类型4. 获取promise返回值类型 1. 准备工作 创建 utils.ts interface User {id: number;name: string;age: number; } interface Params {method: string;url: string; }function getUserList(params: Params,other…

C语言从头学33——内存管理(一)

一、基本情况 C语言的内存管理分成系统管理与程序员用户手动管理两部分。系统管理的内存,主要是函数内部的变量(局部变量),这部分变量在函数运行时进入内存,这部分内存区域成为"栈区",函数…

vue中使用$set方法给对象添加属性

vue中可以使用$set()给对象添加属性,但不是所有的对象都可以使用,vue中api明确说明,它必须用于向响应式对象上添加属性 响应式对象,vue的响应式原理,可以查看:深入响应式原理 — Vue.js ①对象赋值 this…

读懂一本书

各位好,今天我们要分享的这本书叫作《读懂一本书》。 很不好意思,书的作者是我。并不是我写的所有的书我都一定要讲,我也有很多合辑类的书籍是从来不讲的,我讲过《可复制的领导力》,讲过《低风险创业》,还有今天的这本《读懂一本书》,都是我有一些原创的观点和价值在里…

leetcode热题100.单词拆分(动态规划进阶)

最近参加工作比较忙,抽出时间分享一篇题解,希望对大伙有帮助🎈🎈 今天分享一道动态规划的题目,大家快刷起来吧🦾🦾 Problem: 139. 单词拆分 给你一个字符串 s 和一个字符串列表 wordDict 作为字…

React组件间通信的几种方式

一、Props向下传递&#xff08;Top-Down Propagation&#xff09; 父组件通过props将其状态或数据传递给子组件。 父组件&#xff1a; class ParentComponent extends React.Component {state { message: Hello World };render() {return <ChildComponent message{this.…

真正适合零基础的机器学习入门书!数学不好?python不会?通通都能拿下!!

在数字化时代&#xff0c;机器学习无疑是一股强劲的革新动力&#xff0c;正悄无声息地渗透并革新各行各业&#xff0c;成为推动创新、提升效率的关键法宝。 对于想要涉足这个领域&#xff0c;渴望掌握机器学习精髓的初学者来说&#xff0c;《Python机器学习基础教程》就是一本…

C++ list容器的底层实现

一.list是什么 list 是 C容器中的带头双向链表&#xff0c;头结点不存储数据&#xff0c;头结点的下一个元素是第一个存储数据的元素&#xff0c;头结点的前一个元素连接着最后一个存储数据的元素。&#xff08;结构如下图所示&#xff09; 其中链表里每一个节点的结构分为&…

AI究竟是在帮助开发者还是取代他们

前言 人工智能&#xff08;AI&#xff09;的迅猛发展正在各行各业引发深远影响。尤其是在软件开发领域&#xff0c;AI的应用日益广泛&#xff0c;带来了效率和创新的提升。然而&#xff0c;随着AI技术的不断进步&#xff0c;人们也开始担心AI是否会取代人类开发者&#xff0c;…

PyQt5开发笔记:2. 2D与3D散点图、水平布局和边框修饰

一、装pyqtgraph和PyOpenGL库 pip install pyqtgraph pip install PyOpenGL 注意&#xff1a;一定不要pip install OpenGL&#xff0c;否则会找不到 二、3D散点图效果 import pyqtgraph as pg import pyqtgraph.opengl as gl import numpy as np# 创建应用程序 app pg.mkQ…

【计算机组成原理 | 第二篇】计算机硬件架构的发展

目录 前言&#xff1a; 冯诺依曼计算机架构 现代计算机架构&#xff1a; 总结&#xff1a; 前言&#xff1a; 在当今数字化时代&#xff0c;计算机硬件不仅是技术进步的见证者&#xff0c;更是推动这一进步的基石。它们构成了我们日常生活中不可或缺的数字生态系统的核心&a…

数据失踪了?小米手机数据恢复并不难,3个方法就能搞定

手机数据就如同我们的“数字生命线”&#xff0c;一旦失去&#xff0c;便仿佛陷入了一片数据的荒漠&#xff0c;感到无助与迷茫。小米手机用户们&#xff0c;你是否曾遭遇过这样的困境&#xff1a;打开手机&#xff0c;却发现重要的照片、联系人、短信等数据不见了&#xff0c;…

Flutter和React Native(RN)的比较

Flutter和React Native&#xff08;RN&#xff09;都是用于构建跨平台移动应用程序的流行框架。两者都具有各自的优势和劣势&#xff0c;选择哪个框架取决于您的具体需求和项目。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 以下是…

数据库作业六

创建视图v_emp_dept_id_1&#xff0c;查询销售部门的员工姓名和家庭住址 CREATE VIEW v_emp_dept_id_1 AS SELECT e.emp_name,e.address FROM dept d, emp e WHERE e.dept_id (SELECT dept_id FROM dept WHERE dept_name 销售部); SELECT * FROM v_emp_dept_id_1; 创建视…

乐财业:打造财税服务的“硬核“竞争力

乐财业 智慧财税赋能平台 乐财业是目前市面上唯一一家真正实现“业财税”"三位一体全面融合的综合赋能平台&#xff0c;全新打造一站式、流程化、生态化的全产品供应链&#xff0c;立足于企业“业财"融合的发展趋势&#xff0c;凭借20年的财税服务经验&#xff0c;站…

CoreDump使用与实现原理

一、背景 系统发生native crash时&#xff0c;针对内存异常访问、内存踩踏等疑难问题&#xff0c;由于tombstone信息量不足无法精确定位分析这类问题。 二、coredump介绍 2.1 什么是coredump 当用户程序运行过程中发生异常, 程序异常退出时, 由Linux内核把程序当前的内存状…

C语言笔记29 •单链表经典算法OJ题-1.合并两个升序链表•

1.合并两个升序链表&#xff08;创建头节点 简化代码&#xff09; ListNode* lowlisthead(ListNode*)malloc(sizeof(ListNode)); 新颖之处就是创建头节点&#xff08;哨兵位&#xff09;能够减少代码&#xff0c;不用每次都判断链表是否为NULL&#xff0c; 注意的是&#xff1a…