我必须处理一个非常长的数据库表,想一想中止这个循环的最常用方法。主要代码序列就像这样
procedure TForm.ProcessmyTable(Sender : TObject);
begin
.....
myTable.first;
repeat
ReadSingleRecordfromTable ( MyTable, aRecord) ;
ProcessMyRecord(aRecord) ;
MyTable.next;
until MYTable.EOF;
end;
unit .... ;
procedure ProcessMyRecord(aRecord : TMyDataRecord) ;
begin
// do not have user interface stuff here
// Application.Processmessages will not work here !!!
.... ( long running code sequence)
end;
可以做一个计时器并根据定时器打破循环,使用var作为标志支持....但这真的是解决这个问题最聪明的方法吗?
答案 0 :(得分:1)
如果此代码在主线程中运行,那么如果您希望用户与您的程序进行交互并中止,则需要为消息队列提供服务(即调用Application.ProcessMessages
)。在这种情况下,我认为你已经知道了解决方案。致电Application.ProcessMessages
。如果用户选择中止,则设置一个布尔标志并在最内层循环中定期检查该标志。
当然,这一切都很混乱。根本问题是您正在GUI线程上执行长时间运行的操作。这是你不应该做的事情。将数据库处理代码移动到其他线程。如果用户选择中止,则向线程发信号通知它将中止。例如,调用线程的Terminate
方法就是这样做的一种方法。
答案 1 :(得分:0)
您想什么时候中止?如果用户说'停止'
,则需要很长时间在这两种情况下都要更改
until MYTable.EOF;
到
until MYTable.EOF or Aborted;
然后在定时器触发时或用户按下某个键时设置您的Aborted布尔值(请注意,您必须在循环中使用Application.ProcessMessages才能使程序能够处理按键)。这不会在处理例程中中止,而是在每条记录之后。如果速度不够快,则必须显示记录处理程序。
答案 2 :(得分:0)
如果这是一个漫长的过程,用户可能想要在Windows应用程序中中止,那么应与GUI进行一些交互,完成记录计数或进度条(如果不是每个记录然后定期)任何更新标签或进度条的调用都将提供设置中止标志的机会(因此不需要处理消息)。此外,如果用户可以看到一些进展,他们可能不太可能在无聊时中止但95%完成。
恕我直言:)