做了个简单的小程序,主要功能有蓝牙。放了一个 TCircle 在上面,给它增加了一个 TColorAnimation 用于接收到蓝牙数据的时候,变化颜色闪烁,作为接收到数据的提示。
在 WIDNDOWS 底下运行正常;
在 Android 32 底下运行正常;
在 Android 64 底下运行,过几分钟就会出现异常提示:raised exception class Segmentation fault (11).,然后程序就崩溃了。
以为是蓝牙部分导致的问题,彻底把蓝牙部分的代码屏蔽掉,问题依旧存在。
在出现异常时,查看 Call Stack,发现问题出现在 function NewWaitObj: Pointer;
再往上跟,看到是 class procedure TThread.Synchronize;
再往上跟,发现涉及到 procedure TBluetoothLE.DoOnCharacteristicRead;
看起来是蓝牙的问题。把蓝牙的读数据部分的代码,也就是 BluetoothLE1CharacteristicRead 事件方法里面,写一个 Exit,直接跳出,继续测试,问题依旧。此时,Call Stack 仍然是停在 function NewWaitObj: Pointer;这里,往上看,里面有和动画相关的代码。
于是,干脆把动画停掉,再次测试,问题不再出现。
看起来,是蓝牙的 BluetoothLE1CharacteristicRead 事件方法,在内部采用了 TThread.Synchronize,里面采用了 TMonitor;而动画也是线程,最终也要用 TThread.Synchronize 同步到主线程,也同样用到了 TMonitor;然后这两个冲突了?
而且不是一定冲突,是跑几分钟后才冲突。跑了几分钟,TBluetoothLE.DoOnCharacteristicRead 执行了大概 200 次,动画也转了几十圈。
总之,测试结果发现 Delphi 10.4 社区版内部关于 TThread.Synchronize 的代码,在安卓64底下有BUG,具体原因还不清楚。
结论:用 Delphi 写安卓程序,还是尽量不要用它提供的动画控件。