0

谁能提供有关如何在以下情况下实现我想要的建议?(我想知道theads是否会有所帮助,但以前没有使用过它们。)

在我的 Delphi 应用程序中,我有一个通过 Internet 针对外部 MYSQL 数据库运行的查询。查询的结果显示在 DBGrid 中(最多 50 行)。

用户单击按钮进行“网络检查”,然后发生以下情况......

  • 首先,我将数据集的一个字段 (web_response) 设置为空字符串,以清除 DBGrid 中显示的任何现有数据。

  • 然后对于数据集中的每一行,我提取一个字段 (FieldA) 的值,将其传递给一个函数,并将另一个字段 (web_response) 的值设置为该函数的结果。

  • 该函数本身使用 IdHTTP 使用传递的参数在不同的远程网站上执行搜索,并返回一个响应字符串。该过程大约需要 1 到 2 秒。

我想要的效果是让网格“立即”清除所有 Web 响应字段,然后逐行将 Web 响应字段设置为一个值,每个值都按设置显示。

下面的代码可以正常工作,但不能完全给出我需要的效果。我想知道是否在某处使用线程 - 而不是 application.processmessages 可能会改善事情。

我现在得到的效果是网格完全空白一两秒钟,然后重新出现,网络响应列空白。然后,这些行会以大约每 1 秒一行的速度使用 Web 响应进行更新,但每次添加新响应时,网格都会剧烈闪烁。如果线程没有帮助,有没有更好的方法来做我正在做的事情?

我目前使用的代码(更改了标识符以保护无辜者)

//empty any preexisting web responses
//disable controls to stop the DBgrid flickering while we clear out existing web responses
DBGrid1.DataSource.DataSet.DisableControls;
MyQuery1.First;
while not MyQuery1.Eof do
begin
  MyQuery1.Edit;
  MyQuery1.FieldByName('web_response').AsString := '';
  MyQuery1.Next;
end;
DBGrid1.RefreshData; //show cleared grid again
DBGrid1.DataSource.DataSet.EnableControls; 

 //For each row, check FieldA on the web and show response
MyQuery1.First;
while not MyQuery1.Eof do
begin
  DataToCheck := MyQuery1.FieldByName('FieldA').AsString ; //get data to check
  //get the web response and put into dataset
  MyQuery1.Edit;
  MyQuery1.FieldByName('web_response').AsString := GetWebCheckResponse(DataToCheck);
  Application.ProcessMessages; //,'cos the loop is slow <<-- can I get rid of this and use threads?
  DBGrid1.RefreshData; //show the response we just put in dataset
  MyQuery1.Next;
end;
4

3 回答 3

3

自从我上次接触 Delphi 已经 7 年多了,我们不允许使用数据感知组件,所以我可能在这里给你错误的建议。但是,您似乎过于频繁地刷新网格。特别是您正在循环刷新网格。

我建议将代码更改为:

DBGrid1.DataSource.DataSet.DisableControls;
MyQuery1.First;
while not MyQuery1.Eof do
begin
  MyQuery1.Edit;
  MyQuery1.FieldByName('web_response').AsString := '';
  MyQuery1.Next;
end;



//For each row, check FieldA on the web and show response
MyQuery1.First;
while not MyQuery1.Eof do
begin
   DataToCheck := MyQuery1.FieldByName('FieldA').AsString ; //get data to check
   //get the web response and put into dataset
   MyQuery1.Edit;
   MyQuery1.FieldByName('web_response').AsString := GetWebCheckResponse(DataToCheck);
   Application.ProcessMessages; //,'cos the loop is slow <<-- can I get rid of this and use    threads?

   MyQuery1.Next;
end;
DBGrid1.DataSource.DataSet.EnableControls; 
DBGrid1.RefreshData; //show the response we just put in dataset

您可能希望显示一个对话框,说明正在处理,并且在所有完成之前不显示网格。如果记忆对我有用,您可能想查看 DBGrid.BegingUpdate() 和 DBGrid.EndUPdate()。

于 2014-02-13T22:14:36.787 回答
0

我只会将进度条与progressbar1.repaint一起使用;在循环中仅刷新进度,而不是 application.processmessages;

于 2017-11-19T10:49:45.897 回答
0
DBGrid1.DataSource.DataSet.DisableControls;
MyQuery1.First;
while not MyQuery1.Eof do
begin
  MyQuery1.Edit;
  MyQuery1.FieldByName('web_response').AsString := '';
  MyQuery1.Next;
end;
DBGrid1.DataSource.DataSet.EnableControls; 

DBGrid1.RefreshData; 
Application.ProcessMessages;

 //For each row, check FieldA on the web and show response
MyQuery1.First;
while not MyQuery1.Eof do
begin
  DataToCheck := MyQuery1.FieldByName('FieldA').AsString ; //get data to check
  //get the web response and put into dataset
  MyQuery1.Edit;
  MyQuery1.FieldByName('web_response').AsString := GetWebCheckResponse(DataToCheck);
  MyQuery1.Next;

  DBGrid1.RefreshData;
  Application.ProcessMessages;
end;

干杯,范

于 2017-11-19T15:24:47.120 回答