Ошибки и их решения: Обновление свойств VCL элементов после завершения фонового потока в Delphi
При работе с фоновыми потоками в Delphi может возникнуть ситуация, когда после завершения потока необходимо обновить свойства VCL элементов, например, скрыть или показать кнопки. Однако, попытки изменить свойства элементов управления из метода DoTerminate фонового потока могут привести к ошибкам, поскольку этот метод выполняется в контексте потока, который уже завершается.
Проблема
Разработчик столкнулся с проблемой, когда после завершения фонового потока, созданного с помощью метода TThread.DoTerminate, попытки изменить свойства элементов управления (кнопок) приводили к их исчезновению с формы. Также при закрытии формы возникало сообщение об ошибке:
Project ProjectTest.exe raised exception class EOSError with message 'System Error. Code: 1400. Invalid window handle'.
Пример кода
Вот пример кода, который воспроизводит описанную проблему:
type
TFooThread = class(TThread);
TFormSample = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
ProgressBar1: TProgressBar;
// ... другие процедуры ...
private
FooThread: TFooThread;
procedure ThreadIsDone;
public
end;
TFooThread = class(TThread)
private
FForm: TFormSample;
protected
procedure DoTerminate; override;
public
procedure Execute; override;
constructor Create(AForm: TFormSample); reintroduce;
destructor Destroy; override;
end;
constructor TFooThread.Create(AForm: TFormSample);
begin
inherited Create(False);
FreeOnTerminate := False;
FForm := AForm;
end;
procedure TFooThread.DoTerminate;
begin
FForm.ThreadIsDone;
inherited;
end;
procedure TFooThread.Execute;
begin
// ... код выполнения потока ...
Terminate(); // Необязательно вызывать Terminate, поток завершится автоматически
end;
// ... другие процедуры и реализация ...
procedure TFormSample.ThreadIsDone;
begin
// Обновление свойств элементов управления
Button2.Visible := False;
Button3.Visible := True;
end;
Решение проблемы
Изменение свойств VCL элементов из метода DoTerminate не является безопасным, так как этот метод выполняется в контексте потока, который уже завершается. Вместо этого рекомендуется использовать обработчик события OnTerminate, который будет вызван в основном потоке.
Также стоит избегать создания циклических зависимостей между потоком и формой. Лучше всего, если логика, управляющая формами, будет находиться в классе формы.
Альтернативный подход
Инициализация потока может быть выполнена в приостановленном состоянии, а затем поток можно запустить с помощью метода Start. Это позволяет избежать необходимости вызывать Terminate вручную.
Итоги
Не изменяйте свойства VCL элементов из метода DoTerminate.
Используйте обработчик события OnTerminate для обновления интерфейса.
Избегайте циклических зависимостей между потоком и формой.
Если поток создается в приостановленном состоянии, инициализируйте его до вызова inherited Create.
Следуя этим рекомендациям, можно избежать ошибок, связанных с обновлением свойств VCL элементов после завершения фоновых потоков в Delphi.
При работе с фоновыми потоками в Delphi необходимо соблюдать осторожность при изменении свойств VCL элементов после их завершения, чтобы избежать ошибок, связанных с неверным доступом к элементам управления.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.