单独的 TThread 块 GUI 线程中的操作
Posted
技术标签:
【中文标题】单独的 TThread 块 GUI 线程中的操作【英文标题】:Operations in separate TThread block GUI thread 【发布时间】:2011-02-19 18:05:26 【问题描述】:我使用本教程 http://delphi.about.com/od/kbthread/a/thread-gui.htm 创建了一个类,该类使用 TDownLoadURL
在另一个线程中从 Internet 异步下载文件。我这样做是因为我想在不阻塞 UI 线程的情况下下载文件,这样程序就不会在大型下载期间变得无响应、进度条可以更新等。
我遇到了一个问题,因为即使我已经在另一个线程中完成了下载(从 TThread 继承并在 Execute 方法中完成工作),GUI 线程似乎被阻止并且在下载完成之前不会处理消息。这是我的类的代码:http://codepad.org/nArfOPJK(只有 99 行,一个简单的类)。我正在执行它,在按钮单击的事件处理程序中:
var
frame: TTProgressFrame;
dlt: TDownloadThread;
begin
dlt := TDownloadThread.Create(True);
dlt.SetFile('C:\ohayo.zip');
dlt.SetURL('http://download.thinkbroadband.com/512MB.zip');
dlt.SetFrame(frame);
dlt.SetApp(Application);
dlt.Start;
注意:SetApp 方法适用于当我从我的类 TDownloadThread
的 UpdateDownloadProgress
方法内部手动调用 app.ProcessMessages
时。这将防止 GUI 无响应,但它使进度条的行为变得怪异(aero 进度条的移动发光的东西移动得太快了),所以我删除了它。我想正确地解决这个问题,如果我必须打电话给ProcessMessages
,那么多线程真的没有意义。
有人可以帮我解决这个问题吗?谢谢。
【问题讨论】:
代码看起来是正确的(包括你的线程之一)。您是否尝试在调试器下运行它并查看 dlt.Start 的执行速度(即它是立即返回还是...)? @Eugene:不,由于某种原因,Start
不会立即返回,或者根本不会返回,直到下载完成。什么鬼?
@Kokonotsu 不知道,但是您可以将 Classes.pas 添加到您的项目中(如果您有源代码),跟踪 Start 方法并查看给出的结果。
@Eugene,不,我没有 Classes 的来源。我能做什么?
VCL 源代码应该包含在 Delphi 中。
【参考方案1】:
我现在有你的解决方案!
调用TDownLoadURL.Execute
(您在TDownloadThread
中调用dl.Execute
)会导致操作被转移回主线程,这就是您的用户界面变得无响应的原因。
相反,您应该调用ExecuteTarget(nil)
,它不会执行任何此类阴谋并且按您的意愿工作:下载在工作线程上运行。
【讨论】:
@David 查看代码,是什么让主线程在下载线程上等待?就像我说的,Start
在下载完成之前不会返回。这是关于什么的?
@David 不,下载线程就是您在我发布的代码中看到的全部内容。这基本上就是整个项目了,除了主表单按钮处理程序的代码非常少,其中大部分也发布在问题中。
@David 我确定它是 TDownLoadURL,因为我将代码更改为使用 CreateThread 而不是 TThread,所以出于某种原因 TDownLoadURL 导致 GUI 线程等待。
@Kokonotsu 是的,我也一直在调试代码。 TDownloadURL
旨在通过在主线程之外运行 Execute 方法来工作。它通过调用SendAppMessage
回到那里。
@Kokonotsu 我想我现在有答案了!!致电UpdateProgress
时,请确保将电话回拨至Synchronize
。以上是关于单独的 TThread 块 GUI 线程中的操作的主要内容,如果未能解决你的问题,请参考以下文章