2016-06-15 8 views
4

私はDelphi 10.1 BerlinのFireDacで作業しています。FireDac GUIがフリーズ

ユーザーにデータを表示するために、私はTDBEditのようなデータ認識コントロールを使用します。

TFDQueryとTDataSourceを使用してコントロールとリンクします。

これは動作しますが、exectuteに時間がかかる長いSQLクエリはGUIをフリーズします。

長時間実行されているクエリを実行しているときにguiがフリーズするのを防ぐ方法が不思議です。

私はバックグラウンドスレッドを考えていました。私はFireDacは、マルチスレッドで動作できることを読んウィキに

http://docwiki.embarcadero.com/RADStudio/XE6/en/Multithreading_(FireDAC)

しかしエンバカデロのコミュニティフォーラムにthreadジェフOvercashは書いている:私は尋ねたりドミトリー言及を見ていない

一つですバックグラウンドスレッドクエリに対して TDataSourceまたはLiveBindingsを持つことはできません。 の結果を表示するクエリをバックグラウンドでスレッドする場合は、LBまたはDataSourceを切断し、すべてのデータを開いて取得してから、接続を再確立してください。

これらの2つは、バッファが非常に揮発性で、別のスレッド内で移動している間に、カーソルを移動したり、 バッファに照会しようとしています。

また、FireDacを使用してフォームに値を表示する人が私を助けてくれるのかと疑問に思います。

+0

バックグラウンドスレッドの実行中にデータソース/ライブバインディングを接続しようとしましたか?私が見積もりを正しく理解すれば、これはうまくいくはずです。 – mjn

+0

それを試してみてください。ただし、TFDQueryがアクティブでなくなったためにTDataSourceがリセットされるため、切断するとすべてのフォームフィールドが空になります。例えば、DBNavigatorを使用している場合は同じ位置にいません。 – Tommy

+3

TClientDataSetを使用してこれを実行していた場合は、DB認識GUIコンポーネントに接続されているCDS1とします。これを行う方法は、バックグラウンドスレッドでクエリを実行したCDS2 Synchronizeを呼び出してDataプロパティをCDS1に割り当てます。これは必要なものすべてであり、aasignmentは即時になります。 FireDACでも同様のことができると思います。 – MartynA

答えて

5

以下のコードサンプルは、FireDACを使用してバックグラウンドスレッドでMSSqlサーバー からレコードを取得する方法の1つを示しています。これはいくつかの詳細を省略します。たとえば、実際にはTQueryThreadExecuteではクエリを1回だけ開いて終了するのではなく、スレッドのExecuteに、Synchronizeの呼び出し後にセマフォを待ってから/ re - クエリを開いてメインスレッドを必要なだけ頻繁に更新します。

type 

    TForm1 = class; 

    TQueryThread = class(TThread) 
    private 
    FConnection: TFDConnection; 
    FQuery: TFDQuery; 
    FForm: TForm1; 
    published 
    constructor Create(AForm : TForm1); 
    destructor Destroy; override; 
    procedure Execute; override; 
    procedure TransferData; 
    property Query : TFDQuery read FQuery; 
    property Connection : TFDConnection read FConnection; 
    property Form : TForm1 read FForm; 
    end; 

    TForm1 = class(TForm) 
    FDConnection1: TFDConnection; 
    FDQuery1: TFDQuery; 
    DataSource1: TDataSource; 
    DBGrid1: TDBGrid; 
    DBNavigator1: TDBNavigator; 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    public 
    QueryThread : TQueryThread; 
    end; 

[...] 

constructor TQueryThread.Create(AForm : TForm1); 
begin 
    inherited Create(True); 
    FreeOnTerminate := True; 
    FForm := AForm; 
    FConnection := TFDConnection.Create(Nil); 
    FConnection.Params.Assign(Form.FDConnection1.Params); 
    FConnection.LoginPrompt := False; 

    FQuery := TFDQuery.Create(Nil); 
    FQuery.Connection := Connection; 
    FQuery.SQL.Text := Form.FDQuery1.SQL.Text; 
end; 

destructor TQueryThread.Destroy; 
begin 
    FQuery.Free; 
    FConnection.Free; 
    inherited; 
end; 

procedure TQueryThread.Execute; 
begin 
    Query.Open; 
    Synchronize(TransferData); 
end; 

procedure TQueryThread.TransferData; 
begin 
    Form.FDQuery1.DisableControls; 
    Form.FDQuery1.Data := Query.Data; 
    Form.FDQuery1.EnableControls; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    QueryThread.Resume; 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    QueryThread := TQueryThread.Create(Self); 
end; 

MJNのブックマークに関するコメントは、GUIの現在のデータ行の位置を保持する方法を示しています。

Btw、私はTClientDataSetsでこれをしばしばやっていましたが、この回答をまとめてFireDACで試してみました。コンポーネントの設定に関しては、パレットからコンポーネントをドラッグして、それらを一緒に配線し、FDConnectionのParamsとFDQueryのSQLを設定するだけでした。

+0

ありがとう@MartynAこの回答に感謝します。しかし、私はemba wikiのこのサイトをちょうどstumpled:http://docwiki.embarcadero.com/Libraries/XE8/de/FireDAC.Stan.Option.TFDResourceOptions.CmdExecMode。私はCmdExecModeの実行モードを "amNonBlocking"に変更しましたが、現在guiはもはやフリーズしていません。 – Tommy

+0

私の場合、バックグラウンドスレッドは必要ないかもしれませんし、CmdExecModeで十分です。私は他の問題に遭遇したかどうかまだ分かりませんので、さらにテストをしなければなりません。 – Tommy

+0

あなたのためにうまくいくと思われる代替の回答を見つけられたらうれしいです。 – MartynA

関連する問題