В статье мы рассмотрим проблему, с которой сталкиваются разработчики при использовании класса TThread в Delphi 2010, связанную с устареванием метода Resume. Покажем, как правильно создавать и запускать потоки, а также рассмотрим примеры кода на Object Pascal.
Проблема и описание ошибки
В Delphi 2010 метод Resume класса TThread объявлен устаревшим. Разработчики столкнулись с ошибкой, пытаясь использовать стандартный подход:
TMyThread = class(TThread)
protected
procedure Execute; override;
public
constructor Create; override;
end;
var
MyThread: TMyThread;
begin
MyThread := TMyThread.Create(True);
// ... другие инициализации ...
MyThread.Start; // Выдает ошибку: "Cannot call start on a running or suspended thread"
end;
Ожидалось, что после создания потока в приостановленном состоянии (с параметром True в конструкторе) следует вызвать метод Start. Однако появляется исключение, указывающее на попытку запуска уже работающего или приостановленного потока.
Подтвержденное решение
Решение заключается в том, что после создания потока в приостановленном состоянии (inherited Create(True);) не следует вызывать метод Start. Запуск потока происходит автоматически в методе AfterConstruction, который вызывается после всех конструкторов.
Альтернативный ответ
Вместо использования метода Start после создания потока, следует либо:
Создавать поток в приостановленном состоянии и запускать его извне класса, после полной инициализации.
Создавать поток в не-приостановленном состоянии, полностью инициализируя его в конструкторе, и позволить TThread.AfterConstruction запустить поток.
Пример класса потока
unit DecoupledThreadUnit;
interface
uses
Classes;
type
TDecoupledThread = class(TThread)
strict protected
procedure DoExecute; virtual;
procedure DoSetUp; virtual;
procedure DoTearDown; virtual;
protected
procedure DoTerminate; override;
procedure Execute; override;
public
constructor Create;
procedure AfterConstruction; override;
end;
implementation
constructor TDecoupledThread.Create;
begin
inherited Create(True);
end;
procedure TDecoupledThread.AfterConstruction;
begin
DoSetUp();
inherited AfterConstruction;
end;
procedure TDecoupledThread.DoExecute;
begin
// Основной код потока
end;
procedure TDecoupledThread.DoSetUp;
begin
// Инициализация перед запуском потока
end;
procedure TDecoupledThread.DoTearDown;
begin
// Деинициализация после завершения потока
end;
procedure TDecoupledThread.DoTerminate;
begin
inherited DoTerminate;
DoTearDown();
end;
procedure TDecoupledThread.Execute;
begin
DoExecute();
end;
end.
Заключение
Важно понимать, что поток должен быть лишь контекстом выполнения кода, а сам код (логика бизнес-процессов) должна быть реализована в отдельных классах. Это обеспечивает гибкость и возможность использования бизнес-логики в различных местах, что удобно при написании юнит-тестов.
В статье рассматривается проблема разработчиков, связанная с использованием класса `TThread` в Delphi 2010, где метод `Resume` объявлен устаревшим, и предлагаются решения по правильному созданию и запуску потоков с использованием Object Pascal.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.