我在这里有一个遗留应用程序,它有一些"耗时"的循环,由于各种用户交互而被解雇.耗时的代码定期用屏幕上的进度信息(通常是标签)更新某些内容,然后,似乎说服视觉刷新发生在那里,然后,代码调用Application.ProcessMessages(argh!).
我们现在都知道这可以给GUI应用程序带来什么样的麻烦(慈善,那时候是一个更无辜的时间)我们发现它确实像鸡蛋一样,我们不时让用户实现不可能的程序,因为他们在程序"忙"时点击控件.
什么是定期刷新表单视觉而不接受其他事件/消息等的最佳方法?
我的想法是;
- 在执行任何耗时之前禁用所有控件,并保留'... ProcessMessages'调用以"强制"刷新,或者
- 找到另一种方法来定期刷新控件
我可以做前者,但它让我想知道 - 有更好的解决方案吗?
来自遗留的示例代码;
i:=0;
while FJobToBeDone do
begin
DoStepOfLoop;
inc(i);
if i mod 100 = 0 then
begin
UpdateLabelsEtc;
Application.ProcessMessages;
end;
end;
在后面我已经听到你们都昏倒了.:-)
mgh*_*hie 18
如果在更改属性后在控件上调用Update(),则会强制它们重绘.另一种方法是调用Repaint()而不是Refresh(),这意味着调用Update().
您可能还需要在父控件或框架上调用Update(),但这可以允许您完全消除ProcessMessages()调用.
我用于长时间更新的解决方案是在单独的线程中进行计算.这样,主线程保持响应.线程完成后,它会向主线程发送一条Windows消息,指示主线程可以处理结果.
这有一些其他严重的缺点.首先,当另一个线程处于活动状态时,您必须禁用一些控件,因为它们可能会再次重新启动线程.第二个缺点是您的代码需要成为线程安全的.这有时可能是一个真正的挑战.如果您正在使用遗留代码,那么您的代码很可能不是线程安全的.最后,多线程代码更难调试,应由经验丰富的开发人员完成.
但是多线程的最大优点是您的应用程序保持响应,并且用户可以继续执行其他操作,直到线程完成.基本上,您正在将同步方法转换为异步函数.并且线程可以触发几条指示某些控件的消息来刷新它们自己的数据,这些数据会立即更新.(并且在您希望更新它们的那一刻.)
我自己使用过这种技术很多次,因为我觉得它好多了.(但也更复杂.)
| 归档时间: |
|
| 查看次数: |
9624 次 |
| 最近记录: |