【发布时间】:2017-06-26 20:41:41
【问题描述】:
我知道 Delphi 线程已经在很多线程上进行了讨论。我尝试查看它们,但没有找到我的问题的答案。
背景: 我发现在浏览器加载 Adobe Acrobat Reader DC 后释放 TWebBrowser 可能需要 10 多秒。我认为它正在检查更新或其他东西。尝试关闭带有浏览器的表单时很烦人。
我想也许我可以让一个后台线程释放浏览器。所以我把浏览器变量移到了一个全局变量中(私下存放在单元的实现部分)。一次只能使用其中一种形式。然后我试图让一个线程在后台释放它。它没有像我预期的那样工作。
示例代码
interface
TMyform = class(TForm)
pnlBowserHolder: TPanel;
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
//WebBrowser : TWebBrowser; <-- moved to global variable
public
{ Public declarations }
end;
implementation
type
TBackgroundBrowserKillerThread = class(TThread)
public
procedure Execute; override;
end;
var
WebBrowser : TWebBrowser;
BrowserKillerThread : TBackgroundBrowserKillerThread;
procedure TfrmLabImageViewer.FormCreate(Sender: TObject);
begin
WebBrowser := TWebBrowser.Create(Self);
TWinControl(WebBrowser).Parent := pnlBowserHolder;
WebBrowser.Align := alClient;
end;
procedure TfrmLabImageViewer.FormDestroy(Sender: TObject);
begin
BrowserKillerThread := TBackgroundBrowserKillerThread.Create(true);
Application.ProcessMessages;
BrowserKillerThread.Execute();
//WebBrowser.Free;
end;
procedure TBackgroundBrowserKillerThread.Execute();
begin
TWinControl(WebBrowser).Parent := nil;
FreeAndNil(WebBrowser);
self.FreeOnTerminate := true;
BrowserKillerThread := nil; //free reference to thread, shouldn't affect ability of self to free itself (?)
end;
问题:
- 当我在调试模式下单步执行 FormDestroy 代码时,包含 BrowserKillerThread.Execute(); 的行仍然需要 10 秒才能执行。我原以为这会启动另一个线程并立即返回。但事实并非如此。我对 .execute 的理解是错误的吗?或者发生了什么有趣的事情?
- 我的所作所为是坏事吗?我已经读到 VCL 不是线程安全的,并且不能/不应该从另一个线程访问 VCL 对象。我希望这不适用于这种情况,因为我只是释放对象而没有计划进一步的交互。
- 如果线程在终止时自行释放,我认为这会使我的 BrowserKillerThread 指针悬空。那么可以像我一样将 nil 分配给它吗?
- 关于如何更好地做到这一点的任何建议?
提前非常感谢。
KT
【问题讨论】:
-
这永远行不通。除了主线程之外,您无法从任何地方访问任何类型的 VCL 控件,并且您无法在一个线程中创建它并在另一个线程中销毁它。你写的代码并没有改变任何东西——浏览器仍然被拥有它的主线程破坏;您只是从您的线程中调用该代码(这是错误的,除非您通过同步来执行此操作)。
-
另外...您可能想再次查看所有这些主题。我敢打赌,您还没有看到一个从外部调用执行方法的示例。为什么?因为这样execute方法中的代码将在调用它的线程的上下文中运行。
-
使用 TWebBrower + v.15.023 of Acro Reader DC 关闭您描述的应用程序时,我没有收到延迟。您能否举一个导致您延迟的示例 URL?
-
您是否尝试在关闭表单之前导航到 about:blank?
-
感谢大家的帮助。 @MartnyA:我正在打开一个存储在本地文件系统中的 .pdf 文件。
标签: multithreading delphi acrobat twebbrowser