Ich weiß, dass Delphi-Threads auf vielen Threads diskutiert wurden. Ich habe versucht, sie zu überprüfen, fand aber keine Antwort auf meine Frage.Ist dieser Delphi Thread Code korrekt?
Hintergrund: Ich habe festgestellt, dass eine TWebBrowser befreien nehmen 10+ Sekunden, nachdem der Browser Adobe Acrobat Reader DC geladen. Ich denke irgendwie nach Updates oder etwas zu suchen. Es ist ärgerlich, wenn man versucht, ein Formular mit einem Browser zu schließen.
Ich dachte vielleicht könnte ich einen Hintergrund-Thread den Browser freigeben lassen. Also habe ich die Browser-Variable in eine globale Variable verschoben (privat im Implementierungsteil der Unit gespeichert). Nur eine dieser Formen würde gleichzeitig verwendet werden. Dann habe ich versucht, einen Thread frei im Hintergrund zu haben. Es funktioniert nicht so, wie ich es erwartet hätte.
Beispiel Code
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;
Fragen:
- wenn ich durch den Formdestroy Code in der Debug-Modus Schritt wird die Zeile mit BrowserKillerThread.Execute(); dauert noch 10 Sekunden zur Ausführung. Ich hatte gedacht, dass dies den anderen Thread starten und sofort zurückkehren würde. Aber das tut es nicht. Ist mein Verständnis falsch was .execute tut? Oder ist etwas Lustiges los?
- Ist das was ich mache eine schlechte Sache? Ich habe gelesen, dass die VCL nicht threadsicher ist, und dass man nicht auf VCL-Objekte von dem anderen Thread zugreifen kann/sollte. Ich hatte gehofft, dass dies in diesem Fall nicht gelten würde, da ich das Objekt nur frei lasse, ohne weitere Interaktion geplant zu haben.
- Wenn ein Thread frei ist nach Beendigung, nehme ich an, dies würde meinen BrowserKillerThread Zeiger baumeln lassen. Ist es also in Ordnung, so wie ich nil zuzuweisen?
- Irgendwelche Vorschläge, wie man das besser macht?
Vielen Dank im Voraus.
KT
Dies wird nie funktionieren. Sie können von keinem Ort auf ein VCL-Steuerelement irgendeiner Art außer dem Hauptthread zugreifen, und Sie können es nicht in einem Thread erstellen und es in einem anderen Thread zerstören. Der Code, den Sie geschrieben haben, ändert nichts - der Browser wird immer noch von dem Hauptthread zerstört, der ihn besitzt; Sie rufen nur diesen Code von Ihrem Thread (was falsch ist, es sei denn, Sie tun es über Synchronisieren). –
Zusätzlich ... Vielleicht möchten Sie alle diese Threads erneut überprüfen. Ich wette, Sie haben kein einziges Beispiel gesehen, bei dem die execute-Methode von außen aufgerufen wurde. Warum? Denn dann würde der Code in der execute-Methode im Kontext des Threads ausgeführt werden, der ihn aufruft. –
Ich bekomme nicht die Verzögerung beim Schließen der App, die Sie mit TWebBrower + v.15.023 von Acro Reader DC beschreiben. Können Sie eine Beispiel-URL angeben, die die Verzögerung für Sie provoziert? – MartynA