我知道在许多线程上都讨论过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;
问题:
提前非常感谢。
韩国电信
最佳答案
是的。这不是您执行线程处理的方式。通常,首先必须确定在最初启动线程后是否需要对该线程执行任何操作。如果是这样,请保留引用,不要使用FreeOnTerminate
,并且要在线程终止后自行处理线程。如果不这样做,请不要保留引用,设置FreeOnTerminate
并将其发送出去。
您既不会在线程的执行中设置FreeOnTerminate
,也不会保留对具有此设置的线程的全局引用。您也不会通过调用它的Execute
方法来启动线程,而是通过创建非暂停线程或通过调用Start
来启动线程。仅调用Execute
并不会真正启动线程,而是在当前线程的上下文中执行此过程,因此它仍需要10秒钟。
您的示例将变为:
procedure TfrmLabImageViewer.FormDestroy(Sender: TObject);
var BrowserKillerThread: TBackgroundBrowserKillerThread;
begin
BrowserKillerThread := TBackgroundBrowserKillerThread.Create(true);
BrowserKillerThread.FreeOnTerminate := true;
BrowserKillerThread.Start;
end;
procedure TBackgroundBrowserKillerThread.Execute();
begin
TWinControl(WebBrowser).Parent := nil; // I don't think you need to nil the parent here, but probably does no harm
FreeAndNil(WebBrowser);
end;
现在线程正确,但是逻辑仍然错误。正如您已经注意到的,您不得修改除主线程之外的其他线程的VCL对象,这包括
Free
。您必须使用Synchronize
做到这一点,这会破坏线程化的目的。我还认为杀死线程中的浏览器的想法是因为它要花费很长的时间,而只是消除症状,而不是原因。我认为最好首先找出为什么要花这么长时间并加以解决,而不是试图以这种方式规避问题。但这不在此问题的范围内,如果您对此有疑问,则应针对此特定问题询问另一个问题。
关于multithreading - 这个Delphi Thread代码正确吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42126528/