2011-08-11 135 views
0

有两种形式。德尔福:冻结形式

Form2不是自动创建的。

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

如果要做任何形式的Sleep(10000);然后另一个将被冻结。如何防止这种行为?

我的问题:一个大的文本文件(3 MB)连续分配(Lines.Assign)到文本编辑器,这样一种形式被冻结。

我可以用另一种形式解冻(非模态)来显示进度条(一种风格是pbstMarquee)?

+0

睡眠()函数的定义本身是“冻结这个线程”,如果你冻结了主线程,你只能从主线程冻结你所有的形式,因为他们所有的工作。听起来你需要了解win32应用程序设计中消息泵的重要性。 http://en.wikipedia.org/wiki/Event_loop –

+0

有没有*有*真正的理由叫睡眠? –

+0

在前台线程?没有。即使在后台线程中,WaitForSingleObject也会更好。我认为OP使用Sleep()模拟3mb文本文件加载多长时间。 –

回答

6

所有GUI代码都应该从主线程运行,并且看起来好像遵循了该规则。

如果调用Sleep然后调用线程将不执行代码,直到超时时间。如果您从主线程调用Sleep,则消息队列在超时过后才会被泵送。因此,整个应用程序似乎冻结。

为什么从一种形式调用Sleep会影响另一种形式?因为所有GUI组件都来自主线程的单个消息队列。一旦你停止泵送队列,所有的GUI组件停止接受排队的消息像WM_PAINTWM_KEYDOWN

据我了解你的问题是,当你加载3MB文本文件导入编辑控件应用程序将出现挂起。文件的大小对我来说听起来不是很大,一个明显的解决方案是找到一个更好地执行加载的编辑控件。例如,我非常确定记事本,Notepad ++等在加载这些文件时不需要像显示进度那样的步骤。我相当怀疑这些应用程序在加载文件时不会抽出队列,但由于时间短,您不会注意到。

什么你不希望发生的事情是你抽你的队列,让您的GUI响应,进而允许用户启动加载另一个文件,而第一个仍在加载。您需要在处理加载操作时禁用您的UI。模态进度对话框是实现这一目标的一种方式。

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

你可以在状态栏中显示进度,而不是模式对话框,这样做不那么具有侵入性。但是请记住禁用任何会导致可重入执行的UI。

+0

加载大文件时记事本非常慢。它不处理消息,并在加载完成之前挂起。 –

+0

Alexey是对的。尝试用记事本打开3 MB。正如我所想的,Notepad ++不加载整个文件,它向用户显示一部分文件,并在滚动时加载其他文件。我使用SynEdit。我怎样才能加载块?如果要通过字符串添加字符串,它将会很慢。我需要按字节加载字节:) – maxfax

+0

所以有可能加载和100 MB,但100 Mb是不是真的加载。我认为如果连续加载5 Mb,任何程序都会卡住。 – maxfax

0

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