私の連絡先情報
郵便メール:
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Delphi での BLE 開発の場合は、TBlueToothLe をインターフェイスにドラッグし、このコントロールを使用して BLE を開発します(Bluetooth ブレスレットの接続など)。
Delphi に付属するデモには BLEScanner プログラムが含まれており、開発の開始点として使用できます。
上記のプログラムが Windows で実行されている場合、デバイスのスキャン後、デバイス上でマウスをクリックすると、インターフェイスがフリーズし、プログラムが応答しなくなることがあります。タスク管理領域を見ると、確かにプログラムが応答せず、クラッシュしています。
マウスをクリックして、選択したデバイスのサービスをスキャンします。その後、デバイスのサービスが検出されると、TBluetoothLE の OnServicesDiscovered イベントがトリガーされます。このイベントでは、デバイスの複数のサービスがループで読み取られ、その後、特定のサービスについてそのキャラクター名がループで読み取られます。ループが文字を読み取る箇所でクラッシュが発生します。
なぜクラッシュしたのか、わかりません。しかし、解決策を見つけました。コードは次のとおりです。
- procedure TForm6.BluetoothLE1ServicesDiscovered(const Sender: TObject; const AServiceList: TBluetoothGattServiceList);
- var
- ServiceIndex: Integer;
- Service: TBluetoothGattService;
- CharacteristicIndex: Integer;
- Characteristic: TBluetoothGattCharacteristic;
- begin
- //以下代码如果不包到 TTask.Run 里面(原本的代码没有),在 WINDOWS 底下,执行到 for
- //CharacteristicIndex := 0 to Service.Characteristics.Count 会界面冻结,而且单步跟踪也停止
- //了,没有往下执行。
- TTask.Run(
- procedure
- var
- ServiceIndex: Integer;
- CharacteristicIndex: Integer;
- begin
- if AServiceList.Count > 0 then
- begin
- for ServiceIndex := 0 to AServiceList.Count - 1 do
- begin
- Service := AServiceList[ServiceIndex];
-
- TThread.Synchronize(nil,
- procedure
- begin
- Listbox2.Items.Add((ServiceIndex + 1).ToString + ' - ' + Service.UUIDName + ' - ' + Service.UUID.ToString);
- end
- );
-
-
- //以下代码会导致死机,如果断点跟踪,直接就是停在 for 这一行,不会继续往下执行。
- for CharacteristicIndex := 0 to Service.Characteristics.Count - 1 do
- begin
- Characteristic := Service.Characteristics[CharacteristicIndex];
-
- TThread.Synchronize(nil,
- procedure
- begin
- Listbox2.Items.Add(' - ' + Characteristic.UUIDName + ' - ' + Characteristic.UUID.ToString);
- end
- );
-
- end;
-
- end;
- end
- else
- TThread.Synchronize(nil,
- procedure
- begin
- Listbox2.Items.Add('- Access not allowed or no service available');
- end
- );
-
- end
- );
-
- //Listbox1.Enabled := True;
- end;
上記のコードでは、TTask.Run が私によって追加されました。 TThread.Synchronize も私が追加しました。 TTask.Run と TThread.Synchronize を削除すると、残りのコードが Delphi に付属するデモの元のコードになります。
まず、元のコードを TTask.Run に置きます。これは、これらのコードを実行のためにスレッドに入れることを意味します。最初に OnServicesDiscovered イベントを発生させたスレッドを実行させる代わりに。考えられる理由: OnServicesDiscovered をトリガーしたスレッドは、時間のかかるタスクをあまりにも多く実行できません。
Listbox2.Items.Add コードなど、データをインターフェイス コントロールに書き込む必要がある場合、コードはスレッドで実行されます。そこで、TThread.Synchronize を追加します。
私の開発環境
環境が異なると現象も異なる場合があります。したがって、私の開発環境は次のとおりです。
Delphi 11 コミュニティ エディション。
Windows 11 ホームエディション;
コンパイルして実行する対象プログラムはWin32版です。
このデモが Android で上記の問題を起こすかどうかはテストされていません。ただし、Android では TTask.Run を追加した方がよいと思います。
ここで説明するデモは、Delphi をインストールした後、デフォルトでインストールされている場合、デモ プログラムは次のとおりです。
C:UsersPublicDocumentsEmbarcaderoStudio22.0SamplesObject PascalMulti-Device Samplesデバイス センサーとサービスBluetoothBLEScanner
Delphi を使用してブレスレット APP を作成するなど、BLE プログラムを開発することは問題ありません。ただし、TBluetoothLE コントロールの多くのイベントでは、あまり多くのコードを実行しないことが最善であることに注意してください。複雑なビジネス ロジックがある場合は、イベント メソッドで、対応するスレッドを開始するだけで別のスレッドで実行するのが最善です。
Delphi の場合、新しく追加された TTask.Run を使用すると、スレッド クラスを作成する必要があった以前よりもコードの記述方法がはるかに簡単になります。