Исправление ошибок в Delphi: экспорт DLL в EXE с многопоточной формой
Разработчики, использующие Delphi для создания приложений, иногда сталкиваются с неожиданными проблемами при экспорте динамических библиотек (DLL) в исполняемые файлы (EXE). Одна из таких проблем связана с созданием главной формы в потоке, отличном от основного. В контексте данной статьи рассмотрим, как решается проблема создания MainForm в потоке TThread при экспорте DLL в EXE.
Проблема
При разработке приложения на Delphi 2010, которое экспортирует DLL и имеет заголовочный файл с определением library, создается главная форма в отдельном потоке TThread. Код выглядит следующим образом:
var
ActiveThread: TActive;
type
TActive = class(TThread)
protected
procedure Execute; override;
end;
procedure TActive.Execute;
begin
Application.Initialize;
Application.CreateForm(MyForm, form);
Application.Run;
end;
begin
ActiveThread := TActive.Create(True);
ActiveThread.FreeOnTerminate := True;
ActiveThread.Resume;
end.
При загрузке DLL через функцию LoadLibrary, приложение работает корректно. Однако, при попытке экспорта DLL в EXE, изменяя вывод в Options -> Application и меняя заголовочный файл с library на program, и последующей сборке и запуске полученного EXE, приложение подвисает в момент создания формы, конкретно на строке Application.CreateForm(MyForm, form);.
Причины возникновения проблемы
Проблема возникает из-за того, что при компиляции кода как program, программа пытается завершить работу до того, как поток TThread успевает выполнить свою задачу. Это происходит из-за достижения конца программы до того, как Application объект (и связанные с ним потоки) был уничтожен. В результате, основной поток завершается, пока поток TThread все еще выполняется, включая создание главной формы и запуск цикла событий Application.Run.
Решение проблемы
Для решения проблемы необходимо дождаться завершения потока TThread перед завершением программы:
program MyProgram;
uses
Classes, Forms, MyForm;
type
TActive = class(TThread)
protected
procedure Execute; override;
end;
procedure TActive.Execute;
begin
Application.Initialize;
Application.CreateForm(TMyForm, MyForm);
Application.Run;
end;
var
ActiveThread: TActive;
begin
ActiveThread := TActive.Create(False);
ActiveThread.WaitFor;
ActiveThread.Free;
end.
Также, стоит отметить, что использование потока для создания главной формы не является лучшей практикой и может быть устранено, убрав поток совсем:
program MyProgram;
uses
Forms, MyForm;
begin
Application.Initialize;
Application.CreateForm(TMyForm, MyForm);
Application.Run;
end.
В качестве альтернативного подхода, если необходимо использовать общий код между проектами program и library, можно обернуть код инициализации Application в функцию, которая будет вызываться из основного потока:
unit MyApp;
interface
procedure RunMyApp;
implementation
uses
Forms, MyForm;
procedure RunMyApp;
begin
Application.Initialize;
Application.CreateForm(TMyForm, MyForm);
Application.Run;
end;
end.
Использование этой функции в проекте program:
program MyProgram;
uses
MyApp;
begin
RunMyApp;
end.
И в проекте library:
library MyLibrary
uses
Classes, MyApp;
type
TActive = class(TThread)
protected
procedure Execute; override;
end;
procedure TActive.Execute;
begin
RunMyApp;
end;
var
ActiveThread: TActive;
begin
ActiveThread := TActive.Create(True);
ActiveThread.FreeOnTerminate := True;
ActiveThread.Resume;
end.
Таким образом, разработчики могут использовать общий код для program и library, выбирая, в каком потоке будет выполняться инициализация Application.
Описание контекста: При разработке приложения на Delphi, при экспорте DLL в EXE с многопоточной формой, возникают проблемы с корректным запуском программы из-за взаимодействия основного потока и потока создания формы.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.