德尔福:冷冻形式

时间:2011-08-11 05:37:55

标签: multithreading forms delphi

有两种形式。

不会自动创建Form2。

 Form2:=TForm2.Create(Application);
 Form2.Show;

如果要在任何表格中进行Sleep(10000);,则会冻结另一个表格。如何防止这种行为?

我的问题:一个大文本文件(3 Mb)被连续分配(Lines.Assign)到文本编辑器中,因此表单被冻结。

我可以使用其他未冻结的表单(非模态)来显示进度条(样式是pbstMarquee)吗?

2 个答案:

答案 0 :(得分:6)

所有GUI代码都应该从主线程运行,看起来您遵循该规则。

如果你调用Sleep,那么调用线程将不会执行代码,直到超时结束。如果从主线程调用Sleep,则在超时结束之前不会抽取消息队列。因此,整个应用程序似乎都冻结了。

为什么从一个表单调用Sleep会影响另一个表单?因为所有GUI组件都是从主线程的单个消息队列中提供的。一旦停止抽取该队列,所有GUI组件就会停止接收排队的消息,如WM_PAINTWM_KEYDOWN等。

据我所知,您的问题是当您将3MB文本文件加载到编辑控件时,您的应用程序会显示为挂起。那个文件大小对我来说听起来不是很大,一个明显的解决方案是找到一个更好地执行加载的编辑控件。例如,我非常确定Notepad,Notepad ++等在加载此类文件时不会采取显示进度的步骤。我宁愿怀疑那些应用程序在加载文件时不会排队,但由于时间很短,你只是没有注意到。

您不希望发生的事情是您抽取队列以保持GUI响应,从而允许用户在第一个文件仍在加载时开始加载另一个文件。您需要在处理加载操作时禁用UI。模态进度对话框是一种方法。

如果无法切换到性能更佳的控件,可以显示模态进度对话框并使用这样的后台线程。后台线程会将文件加载到小块中,比如加入字符串列表。在文件的每个块准备好之后,它将调用Synchronize并获取主线程以将字符串列表的内容添加到编辑控件,然后清除字符串列表。然后线程将继续并加载下一个块。以小块添加到编辑控件将允许您保持消息队列的服务。

您可以在状态栏中显示进度,而不是模式对话框,这样可以减少干扰。但是请记住禁用任何会导致重入执行的UI。

答案 1 :(得分:0)

更好地在单独的线程中加载您的文件。或者您必须在普通的WinAPI中创建第二个表单,因为VCL不支持多线程。