Я знаю, что потоки Delphi обсуждались на многих потоках. Я попробовал пересмотреть их, но не нашел ответа на мой вопрос.Правильно ли этот код в Delphi Thread?
фона: Я обнаружил, что освобождая TWebBrowser может занять 10+ второй после того, как браузер загружен Adobe Acrobat Reader DC. Я думаю, что как-то это проверяет наличие обновлений или что-то в этом роде. Это раздражает при попытке закрыть форму с помощью браузера.
Я подумал, что, возможно, у меня может быть фоновый поток, выпущенный браузером. Поэтому я переместил переменную браузера в глобальную переменную (конфиденциально сохраненную в части реализации модуля). Только одна из этих форм будет использоваться одновременно. Затем я попытался освободить поток в фоновом режиме. Это не работает, как я ожидал.
Пример кода
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 свисает. Так нормально ли назначать ноль этому, как я?
- Любые предложения о том, как это сделать лучше?
Большое спасибо.
KT
Это никогда не сработает. Вы не можете получить доступ к элементу управления VCL любого вида из любого места, кроме основного потока, и вы не можете создать его в одном потоке и уничтожить его в другом. Код, который вы написали, ничего не меняет - браузер по-прежнему уничтожается основным потоком, которому он принадлежит; вы просто вызываете этот код из своего потока (что неправильно, если вы не делаете это через Synchronize). –
Дополнительно ... Возможно, вы захотите снова просмотреть все эти темы. Бьюсь об заклад, вы не видели ни одного примера, вызывающего метод execute извне. Зачем? Потому что тогда код в методе выполнения будет выполняться в контексте потока, который его вызывает. –
Я не получаю задержку при закрытии приложения, которое вы описываете, используя TWebBrower + v.15.023 Acro Reader DC. Можете ли вы привести пример URL-адреса, который вызывает задержку для вас? – MartynA