【发布时间】:2023-04-06 22:30:01
【问题描述】:
有什么解决方案可以避免我的 UI 在等待来自数据库的数据时冻结??
例子:
我们有一个 adoquery,我们有
adoquery.active:=false; adoquery.active:=true;
当 adoquery 尝试从数据库中获取数据时,UI 中的所有内容都被冻结,如果用户单击,则整个程序变为 没反应!!
有没有办法解决这个问题?
【问题讨论】:
有什么解决方案可以避免我的 UI 在等待来自数据库的数据时冻结??
例子:
我们有一个 adoquery,我们有
adoquery.active:=false; adoquery.active:=true;
当 adoquery 尝试从数据库中获取数据时,UI 中的所有内容都被冻结,如果用户单击,则整个程序变为 没反应!!
有没有办法解决这个问题?
【问题讨论】:
您可以在 ExecuteOptions 中使用 [eoAsyncExecute,eoAsyncFetch],这将要求数据集使用显式 TAdoConnection。
为避免出现意外行为,您必须在打开数据集之前使用DisableControls,在FetchComplete 之后使用EnableControls。
在FetchComplete 中直接调用EnableControls 可能会导致异常,因此需要使用带有用户定义消息的Postmessage。
Const
// define a message for handling completed AsyncFetch after leaving FetchComplete
WM_MYConnect=WM_User + 77;
type
TMyForm = class(TForm)
MyDataSet: TADODataSet;
MyDatasource: TDataSource;
DBGrid1: TDBGrid;
Button1: TButton;
ADOConnection1: TADOConnection;
procedure Button1Click(Sender: TObject);
procedure MyDataSetFetchComplete(DataSet: TCustomADODataSet; const Error: Error; var EventStatus: TEventStatus);
private
{ Private-Deklarationen }
Procedure ConnectDatasource(var MSG:TMessage); message WM_MYConnect;
public
{ Public-Deklarationen }
end;
var
MyForm: TMyForm;
implementation
{$R *.dfm}
procedure TMyForm.Button1Click(Sender: TObject);
begin
MyDataset.Close;
// example blocking command for SQL-Server 10 seconds
MyDataset.CommandText := 'WAITFOR DELAY ''00:00:10'' Select* from aa';
Mydataset.DisableControls;
Mydataset.ExecuteOptions := [eoAsyncExecute,eoAsyncFetch];
MyDataset.Open;
end;
procedure TMyForm.ConnectDatasource(var MSG:TMessage);
begin
TAdodataset(MSG.WParam).EnableControls;
// MyDataSource.DataSet := MyDataset;
end;
procedure TMyForm.MyDataSetFetchComplete(DataSet: TCustomADODataSet; const Error: Error; var EventStatus: TEventStatus);
begin
// if we want to add a datasource we will have to ensure that it will happen after leaving FetchComplete
// so we call our procedure ConnectDatasource via PostMessage
PostMessage(Handle,WM_MYConnect,wParam(DataSet),0);
end;
end.
【讨论】: