有没有比这更好的方法来阻止DBgrid闪烁与耗时的更新?

时间:2014-02-13 21:31:37

标签: mysql delphi tdbgrid

在下面的情况下,有人可以提供如何实现我想要的建议吗? (我想知道theads是否有帮助,但之前没有使用它们。)

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

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

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

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

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

我想要的效果是让网格“瞬间”清除所有网络响应字段,然后逐行将网络响应字段设置为一个值,每个值都会在设置时显示。

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

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

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

//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;

3 个答案:

答案 0 :(得分:1)

自从我上次接触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(),如果内存服务我的话。

答案 1 :(得分:0)

我只使用进度条和progressbar1.repaint;在循环中刷新进度,而不是application.processmessages;

答案 2 :(得分: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;

干杯, 范