非同期実行(FireDAC)
コマンドの操作(FireDAC) への移動
概要
プログラマは、ResourceOptions.CmdExecMode プロパティを使って、以下の 4 つの操作モードから選択できます。
モード | 説明 |
---|---|
amBlocking | 呼び出し元スレッドと GUI は、アクションが完了するまでブロックされます。 |
amNonBlocking | 呼び出し元スレッドは、アクションが完了するまでブロックされます。GUI はブロックされません。 |
amCancelDialog | 呼び出し元スレッドと GUI は、アクションが完了するまでブロックされます。ダイアログが表示され、そこでアクションをキャンセルできます。 |
amAsync | 呼び出しスレッドおよび GUI は、ブロックされます。The called method returns immediately. |
アプリケーションでは、TFDCommand.State または TFDAdaptedDataSet.Command.State を調べて操作の状態(以下のいずれか)を確認できます。
状態 | 説明 |
---|---|
csInactive | コマンドが準備されていません。 |
csPrepared | コマンドが準備されています。結果にはアクセスできません。 |
csExecuting | コマンドが実行中です。 |
csOpen | コマンドの実行が終了しました。結果セットはアクセス可能ですが、まだ全体は取得されていません。 |
csFetching | 結果セットの取得が進行中です。 |
csAborting | コマンド実行の中止が進行中です。 |
以下に例を示します。
FDQuery1.ResourceOptions.CmdExecMode := amAsync;
FDQuery1.Open;
while FDQuery1.Command.State = csExecuting do begin
// do something while query is executing
end;
amCancelDialog モードでは、長時間かかる操作の場合は、そのことがユーザーに通知され、ユーザーが次のような TFDGUIxAsyncExecuteDialog コンポーネントを使ってその操作をキャンセルできます。
このダイアログ コンポーネントを使用するには、それをフォームにドロップします。それ以上のセットアップは不要です。操作モードと通知イベントの詳細については、ResourceOptions.CmdExecMode プロパティの説明を参照してください。
非同期の開始と取得
アプリケーションでクエリを非同期的に開始する必要があり(amAsync モード)、かつ、そのクエリが TDataSource を使って GUI にバインドされている場合、クエリを開始する前にその TDataSource をクエリからいったん接続解除し、クエリを開始した後に接続し直す必要があります。以下に例を示します。
procedure TForm1.FDQuery1BeforeOpen(DataSet: TDataSet);
begin
DataSource1.DataSet := nil;
end;
procedure TForm1.FDQuery1AfterOpen(DataSet: TDataSet);
begin
DataSource1.DataSet := FDQuery1;
FDQuery1.ResourceOptions.CmdExecMode := amBlocking;
end;
FDQuery1.BeforeOpen := FDQuery1BeforeOpen;
FDQuery1.AfterOpen := FDQuery1AfterOpen;
FDQuery1.ResourceOptions.CmdExecMode := amAsync;
FDQuery1.Open;
これは、amCancelDialog が使用される場合は不要です。また、GUI を使った取得は、amAsync モードでは実行できません。クエリを開始し、大量の結果セットを非同期的に取得するには、FetchOptions.Mode を fmAll に設定します。その場合、どちらの操作も単一のバックグラウンド タスクとして実行されます。
- メモ: この処理は、双方向データセットを使用する場合にのみ有効です。
Firebird クエリを非同期的に実行するには、そのクエリに別個のトランザクションを使用します。
長時間かかる操作のキャンセル
プログラムでは、ResourceOptions.CmdExecTimeout プロパティを使って、データ アクセス操作のタイムアウトを指定できます。操作の実行に必要な時間が指定の時間を上回る場合は、実行がキャンセルされ、例外が発生します。コマンドのタイムアウトを捕捉するには、次のようなコードを使用します。
try
// set timeout to 5 seconds
FDQuery1.ResourceOptions.CmdExecTimeout := 5000;
FDQuery1.ExecSQL;
except
on E: EFDDBEngineException do
if E.Kind = ekCmdAborted then
; // command is aborted
end;
あるいは、アプリケーションでは、他のスレッドからデータセットまたはコマンドの AbortJob メソッドを呼び出すことで操作の実行をキャンセルできますし、接続の AbortJob メソッドを呼び出して、その接続を通じて実行されているすべての操作をキャンセルすることもできます。
- メモ: すべての FireDAC ドライバおよび DBMS で実行のキャンセルがサポートされているわけではありません。また、DBMS で一部の非常に重要な操作が実行されている場合は、キャンセルをすぐに実行することはできません。サポートされている組み合わせの一覧を以下の表に示します。
DBMS | メモ |
---|---|
Advantage | |
IBM DB2 | |
Firebird | バージョン 2.5 以降 |
Informix | |
InterBase | バージョン 7.0 以降 |
MySQL | バージョン 5.0 以降 |
Oracle | |
PostgreSQL | |
SQL Anywhere | |
SQL SERVER | |
SQLite | |
Teradata Database |
複数の非同期クエリ
複数の非同期クエリの同時実行は、マルチスレッド処理の一般原則のために、FireDAC ではサポートされていません。この問題を回避するには、以下の選択肢を検討します。
- いくつかのクエリを 1 つのストアド プロシージャにまとめ、そのプロシージャを非同期的に呼び出す。
- 同時に実行される非同期クエリごとに専用の接続を使用する。
- 前の非同期クエリが完了してから、次の非同期クエリを起動する。それには、AfterOpen および AfterExecute イベント ハンドラを使用します。
- アプリケーションでそれ専用のスレッドを作成し、それらのスレッドで DB タスクを実行する。