Некорректная Работа В Dll

Shouldercannon

Well-known member
25.05.2010
128
0
#1
Project1 - первый прикреплённый *.pas
DLL
Код:
library dll;

uses
SysUtils,
Windows,
Dialogs,
Controls,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

procedure ShowInfo(Win: Integer); stdcall;
begin
Form1[Win] := TForm1.Create(nil);
Form1[Win].Show;
end;

function FormClosed(Win: Integer): Integer;
begin
if not Form1[Win].Visible then
begin
Form1[Win].Release;
Result := 1;
end
else Result := 0;
end;

exports
ShowInfo, FormClosed;

begin
end.
Unit DLL - второй прикреплённый *.pas
1. В DoTerminate выполняется только одно событие
2. Прогресс бар при последующих закачках не двигается и вообще неправильно показывает прогресс
3. Нулевая реакция на синхронизацию (написанные там события не выполняются)

Тоже самое без DLL работает Великолепно. В чём проблема или это неизбежный косяк DLL?
 

Вложения

sinkopa

Well-known member
17.06.2009
344
4
#2
1. В DoTerminate выполняется только одно событие
2. Прогресс бар при последующих закачках не двигается и вообще неправильно показывает прогресс
3. Нулевая реакция на синхронизацию (написанные там события не выполняются)

Тоже самое без DLL работает Великолепно. В чём проблема или это неизбежный косяк DLL?
А как Вы хотели... "здесь Вам не тут"... :)
Использовать формы из DLL не так просто... Нет у меня сил лекцию читать, ищите соответствующую информацию в сети.
Могу дать несколько замечаний.
1. Никакого Application в DLL нету... Точнее ок есть как объект (раз уж в uses присутствует модуль Forms). Но он не инициализирован. Вы же не прописывали ему (Application) свойства ExeName и Handle? И Приложение (загрузившее DLL) тоже этого не делало (и не обязано). Так откудаж им взяться?
Поэтому, чтобы DLL знала путь - нужно его передать через експортируемую процедуру (как параметр)... или же берите его из пути к самой DLL
Код:
function DllSelfName(): string;
var
DllFileName: array[0..MAX_PATH] of Char;
begin
FillChar(DllFileName, SizeOf(DllFileName), #0);
GetModuleFileName(hInstance, DllFileName, MAX_PATH);
Result := StrPas(DllFileName);
end;
2. В DLL (с формами) главной проблемой как раз и является "поломанные" цепочки сообщений. В EXE за них отвечает Application который, как уже было сказано, (в DLL) не инициализирован.
Частично ситуацию спасает принудительная инициализация Handle. Вот тут посмотрите примерчик:
http://delphiworld.narod.ru/base/use_form_from_dll.html
3. Synchronize(SyncProc); Делает следующее:
- приостанавливает текущий потокж
- передает управление основному потоку для выпонения кода который в SyncProc;
Поскольку основным потоком у Вас является Приложение (всего лишь вызвавшее функцию внешней DLL) у меня к Вам вопрос:
Как Вы считаете? А знает ли основной поток что нибудь про SyncProc? И наоборот - может ли поток рожденный в DLL что нибудь знать про основной поток? ;)
4. Поскольку в DLL (как я уже сказал) у форм есть проблемы с цепочками сообщений, "слушальщик" формы может не получать Ваш PostMessage.
Я не эксперементировал на эту тему, но возможно эти мессаги Вам придется ловить не "слушальщиком" а непосредственно в оконной процедуре окна. Можно еще попробовать передавать данные через метод формы Perform.
5. Вы в курсе что SetWindowLong пересоздает окно? Почему не назначить дополнительные параметры на CreateParams формы?
6. Почитал Ваш код еще раз... и честно говоря не понимаю, зачем вообще в данной "связке" (Одна форма/одна кнопка/одна загрузка) нужен еще и TDownLoader_Thread? Нельзя разве все выполнить на Button1Click? Неужели только из за того чтобы форма не подтормаживала? :)
Ну так не проще разве в "критических" местах кода вставить Application.ProcessMessages;?
Ну... в самом "тяжелом" случае... можно создавать поток единственной задачей которого будет "шевеление" прогрессбара... (например через критическую секцию) разве нет?
У меня пока все...
блин... один хрен лекция получилась... может мне в преподы надо было пойдти? :)
 

Shouldercannon

Well-known member
25.05.2010
128
0
#3
3. Судя из выше сказанного - не может.
5. Теперь знаю. Код с
Код:
SetWindowLong
был написан не мной, трогать не стал.
6.
Неужели только из за того чтобы форма не подтормаживала?
именно из-за этого. После долгий мучений решил так как есть. Пусть подтормаживает.

блин... один хрен лекция получилась... может мне в преподы надо было пойдти?
Думаю, над этим стоит подумать, так как хорошо получается.
P.S. Больше не буду пытаться делать что-либо в потоке в DLL.