Форум: "Основная";
Текущий архив: 2004.11.14;
Скачать: [xml.tar.bz2];
ВнизDll и TThread Найти похожие ветки
← →
dms_main © (2004-10-29 10:02) [0]Уважаемые мастера, обнаружил такой глюк.
Есть класс на основе стандартного Tthread,
креатится так:
constructor tmythread.create;
begin
inherited create(false);
end;
Проблема в том , что в dll невызывается execute, хотя в console Application все работало замечательно.
Как лечить?
← →
Sandman25 © (2004-10-29 10:04) [1]В execute стоит Synchronized(MyMethod)?
← →
dms_main © (2004-10-29 10:05) [2]нет есть только CriticalSection....
← →
Reindeer Moss Eater © (2004-10-29 10:12) [3]Проблема в том , что в dll невызывается execute,
Потому что Resume не вызван
← →
Reindeer Moss Eater © (2004-10-29 10:14) [4]Или вообще не создан экземпляр
← →
dms_main © (2004-10-29 10:15) [5]TO Reindeer Moss Eater
1.кретиться не suspended
2.креатил с suspended , потом делал resume - непомогает.....
← →
dms_main © (2004-10-29 10:17) [6]все действия записанные в креате (с инкрементом threadcount(integer)) в critical section)проходят , а вот execute не вызывается....:-(
← →
Reindeer Moss Eater © (2004-10-29 10:17) [7]Чем получено знание, что Execute не вызывается?
← →
dms_main © (2004-10-29 10:18) [8]дебагом
← →
Reindeer Moss Eater © (2004-10-29 10:20) [9]Оптимизация или неправильный "дебаг"
← →
Reindeer Moss Eater © (2004-10-29 10:21) [10]Либо все таки не вызван конструктор.
Код вызова констсруктора написан, но он не вызывается.
← →
dms_main © (2004-10-29 10:23) [11]ну насчет дебага : при креате создается файл (свой для каждого трэда),при execute он заполняется. Итог файл создан но незаполнен.
← →
Reindeer Moss Eater © (2004-10-29 10:24) [12]код Execute показывай
← →
Reindeer Moss Eater © (2004-10-29 10:25) [13]Итог файл создан но незаполнен.
Создается один файл, а execute пишет в другой.
← →
Reindeer Moss Eater © (2004-10-29 10:26) [14]хотя в console Application все работало замечательно.
Глобальные переменные тому виной.
Как пить дать.
Имя файла например.
← →
dms_main © (2004-10-29 10:28) [15]имя файла предается трэду через параметр в креате.
в каждом трэде - уникальное
← →
Reindeer Moss Eater © (2004-10-29 10:29) [16]Код давай уже, да?
← →
Reindeer Moss Eater © (2004-10-29 10:30) [17]имя файла предается трэду через параметр в креате.
Что-то я не вижу, что передается.
Читая твой первый постинг.
← →
dms_main © (2004-10-29 10:33) [18]
var
List:textfile;
assignfile(list,drive+".txt");
rewrite(list);
FindFile(drive+":\round.txt");
closefile(list);
checkList:=TStringList.Create;
checklist.Duplicates:=dupIgnore;
checklist.Sorted:=true;
checkList.LoadFromFile(drive+".txt");
checklist.SaveToFile(drive+".txt");
checklist.Clear;
parseFile(drive+".txt");
end;
mycountsection:=TcriticalSection.Create;
mycountsection.Enter;
try
threadcount:=threadcount-1;
finally
mycountsection.Leave;
mycountsection.Free;
end;
← →
dms_main © (2004-10-29 10:34) [19]
constructor tmythread.create(drive:char);
begin
inherited create(false);
end;
было б в нем дело......
← →
Reindeer Moss Eater © (2004-10-29 10:37) [20]Это что? код Execute?
И нафик тогда там критическая секция которая создается при входе и уничтожается при выходе?
Кого она синхронизирует?
Что такое Drive? Поле класса или переменная модуля?
В общем бред какой-то.
И где все же передается имя файла?
← →
dms_main © (2004-10-29 10:40) [21]
> Что такое Drive? Поле класса или переменная модуля?
Drive : char - смотри след. пост
> И нафик тогда там критическая секция которая создается при
> входе и уничтожается при выходе?
> Кого она синхронизирует?
пременная threadcount:integer - счетчик трэдов...
и вообще мы от темы ушли - дело не в том что выскакивает ошибка - дело в том что execute метод не вызывается вообще.....
← →
Reindeer Moss Eater © (2004-10-29 10:42) [22]Drive : char - смотри след. пост
Да пофик чар она или стринг!
Переменная это или член класса потока?!
← →
dms_main © (2004-10-29 10:43) [23]
> Да пофик чар она или стринг!
> Переменная это или член класса потока?!
член класса потока - естественно...
← →
Reindeer Moss Eater © (2004-10-29 10:47) [24]В общем так.
Твоя критическая секция - полный бред.
А что бы убедиться, что Execute все же вызывается, вставь первой строкой в него:
with TFileStream.Create(Format("%d-log.txt",[GetCurrentThreadID]),fmCreate) do
try
WriteBuffer("А все таки она вертиться",24);
finally
Free;
end;
← →
Reindeer Moss Eater © (2004-10-29 10:49) [25]constructor tmythread.create(drive:char);
begin
inherited create(false);
end;
было б в нем дело......
И где сохранение параметра в классе?
← →
Reindeer Moss Eater © (2004-10-29 10:50) [26]Обсуждается какой-то мифический несуществующий код.
На кофейной гуще и то эффективнее гадать получается.
← →
dms_main © (2004-10-29 10:52) [27]
> В общем так.
> Твоя критическая секция - полный бред.
это для тебя бред
я туда messagebox и MessageBeep($FFFFFFFF) вставлял пофиг...
дело не в том бред или нет - там все проверено....
дело в том что метод create вызывается, а execute нет....
вот где загвоздка....
← →
dms_main © (2004-10-29 10:53) [28]млин ща весь выложу...
← →
Reindeer Moss Eater © (2004-10-29 10:54) [29]это для тебя бред
Это бред не только для меня.
а execute нет....
Читай [24] и не свисти MessageBeep"ом
← →
Reindeer Moss Eater © (2004-10-29 10:55) [30]млин ща весь выложу...
Уже не надо.
← →
dms_main © (2004-10-29 10:55) [31]
TMyThread = class(TTHread)
drive:char;
list:textfile;
checkList,sum:TStringList;
mysection:TcriticalSection;
mycountsection:TcriticalSection;
constructor create(adrive:char);
destructor free;
procedure execute;override;
procedure FindFile(path:string);
procedure parseFile(name:string);
end;
constructor tmythread.create(adrive:char);
var
p:pointer;
begin
inherited create(false);
assignfile(list,adrive+".txt");
rewrite(list);
drive:=adrive;
FreeOnTerminate:=true;
Priority:=tpNormal;
mycountsection:=TcriticalSection.Create;
mycountsection.Enter;
try
threadcount:=threadcount+1;
finally
end;
mycountsection.Leave;
mycountsection.Free;
end;
destructor tmythread.free;
begin
inherited free;
end;
procedure TMythread.execute;
begin
assignfile(list,drive+".txt");
rewrite(list);
FindFile(drive+":\round.txt");
closefile(list);
checkList:=TStringList.Create;
checklist.Duplicates:=dupIgnore;
checklist.Sorted:=true;
checkList.LoadFromFile(drive+".txt");
checklist.SaveToFile(drive+".txt");
checklist.Clear;
parseFile(drive+".txt");
end;
mycountsection:=TcriticalSection.Create;
mycountsection.Enter;
try
threadcount:=threadcount-1;
finally
mycountsection.Leave;
mycountsection.Free;
end;
end;
← →
Reindeer Moss Eater © (2004-10-29 10:58) [32]Все твои критические секции только пожирают ресурсы и никого нахрен не синхронизируют.
Они - бред сивой кобылы.
А про вызов Execute читай в 24 посте.
← →
dms_main © (2004-10-29 11:04) [33]1:
> А что бы убедиться, что Execute все же вызывается, вставь
> первой строкой в него:
>
> with TFileStream.Create(Format("%d-log.txt",[GetCurrentThreadID]),fmCreate)
> do
> try
> WriteBuffer("А все таки она вертиться",24);
> finally
> Free;
> end;
нифига непишется
2:
в taskmanager есчетчик трэдов - их там в проге нужное кол-во
так execute и не вызвался...... :-((
← →
Reindeer Moss Eater © (2004-10-29 11:06) [34]Вставил не первой строкой, либо конструктор не вызван.
Аналогичный код в конструктор.
← →
Reindeer Moss Eater © (2004-10-29 11:07) [35]Либо процесс вообще не имет прав на томе на создание файлов
← →
Digitman © (2004-10-29 11:08) [36]это даже скомпилировано быть не может
какой уж разговор о куче несуразностей собственно в алгоритме ..
← →
sniknik © (2004-10-29 11:08) [37]> Обсуждается какой-то мифический несуществующий код.
> На кофейной гуще и то эффективнее гадать получается.
не расстраивайся, все просто, учись отвечать. ;о)
2 dms_main
у тебя ошибка в 17-й (семнадцатой) строке! че ты сюда 18-е (восемнадцатые) лепиш?
> я туда messagebox и MessageBeep($FFFFFFFF) вставлял пофиг...
VCL-ные или системные?
а секция действительно бред. что с чем синхронизируется, если оно все в одном блоке.
← →
Reindeer Moss Eater © (2004-10-29 11:09) [38]не расстраивайся, все просто, учись отвечать. ;о)
Я и других еще научу.
← →
dms_main © (2004-10-29 11:10) [39]
> Вставил не первой строкой, либо конструктор не вызван.
>
> Аналогичный код в конструктор.
работает
> Либо процесс вообще не имет прав на томе на создание файлов
почему тогда это код в апликухе работает?
Апликуха которая грузит dll имеет права на создание файлов....
← →
Reindeer Moss Eater © (2004-10-29 11:11) [40]почему тогда это код в апликухе работает?
Потому что там работает другой код
← →
dms_main © (2004-10-29 11:11) [41]
> это даже скомпилировано быть не может
делфа у меня (5 и 7) кривые - компилят кривой код.... :-)))
← →
dms_main © (2004-10-29 11:12) [42]
> Потому что там работает другой код
как это понимать?
← →
Reindeer Moss Eater © (2004-10-29 11:15) [43]Слева направо
← →
dms_main © (2004-10-29 11:17) [44]Воощем тут все ясно ......
все ушли от темы - помочь в итоге никто не в состоянии .....
← →
Reindeer Moss Eater © (2004-10-29 11:18) [45]Иногда и медицина бессильна
← →
Digitman © (2004-10-29 11:20) [46]
> делфа у меня (5 и 7) кривые - компилят кривой код
дурью маешься, да ?
при чем здесь версия Делфи ? ты прявила Паскаля нарушил !
procedure TMythread.execute;
begin
assignfile(list,drive+".txt");
rewrite(list);
FindFile(drive+":\round.txt");
closefile(list);
checkList:=TStringList.Create;
checklist.Duplicates:=dupIgnore;
checklist.Sorted:=true;
checkList.LoadFromFile(drive+".txt");
checklist.SaveToFile(drive+".txt");
checklist.Clear;
parseFile(drive+".txt");
end;
mycountsection:=TcriticalSection.Create;
mycountsection.Enter;
try
threadcount:=threadcount-1;
finally
mycountsection.Leave;
mycountsection.Free;
end;
end;
то что подчеркнуто, это к чему относится ?
тело процедуры Execute - это то что между begin..end у тебя, а следом что за галиматься идет, скажи на милость ?
← →
sniknik © (2004-10-29 11:21) [47]> как это понимать?
ты не то показываеш, хочеш чтобы по 18й строке нашли глюк в 17й. а то что показываеш нельзя назвать кодом, это один сплошной глюк, не скомпилится.
либо здесь урезано так что принимает другой вид.
← →
sniknik © (2004-10-29 11:23) [48]> Иногда и медицина бессильна
ага, и тогда больной выживает. ;о)) (в смысле глюк, в этом случае)
← →
dms_main © (2004-10-29 14:44) [49]Хорошо - мы пойдем другим путем - если руки у меня кривые, то подскажите где именно:
library finer_lib;
uses
SysUtils,windows,
Classes;
type TMyThread = class (TThread)
a:integer;
b:integer;
c:integer;
constructor create(a0,b0:integer);
destructor free;
procedure execute;override;
end;
constructor TMyThread.create(a0,b0:integer);
begin
inherited create(false);
a:=a0;
b:=b0;
FreeOnTerminate:=true;
end;
destructor TMyThread.free;
begin
inherited free;
end;
procedure TMyThread.execute;
var
t:TstringList;
begin
c:=a*b;
t:=TStringList.Create;
t.Add("Result = "+inttostr(c));
t.SaveToFile("c:\result.nfo");
t.Free;
end;
{$R *.RES}
var
thread:TMyThread;
begin
thread:=TMyThread.create(2,2);
thread.WaitFor;
end.
Execute попрежнему не вызывается.....
← →
dms_main © (2004-10-29 14:46) [50]загрузка dll-ки :
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
windows;
begin
readln;
LoadLibrary("finer_lib.dll");
readln;
end.
← →
Reindeer Moss Eater © (2004-10-29 14:48) [51]Зашибись!
А где запуск чего либо из DLL?
← →
Reindeer Moss Eater © (2004-10-29 14:50) [52]Reindeer Moss Eater © (29.10.04 10:14) [4]
Или вообще не создан экземпляр
← →
dms_main © (2004-10-29 14:51) [53]а зачем после загрузки сразу выполняется begin...end.
begin
thread:=TMyThread.create(2,2);
thread.WaitFor;
end.
Можешь проверить.....
← →
dms_main © (2004-10-29 14:52) [54]
> Reindeer Moss Eater © (29.10.04 10:14) [4]
> Или вообще не создан экземпляр
создается - проверено дэбагом....
← →
Reindeer Moss Eater © (2004-10-29 14:52) [55]Можешь проверить.....
Для начала надо проверить результат LoadLibrary
← →
dms_main © (2004-10-29 14:54) [56]возвращает хэндл....
← →
Reindeer Moss Eater © (2004-10-29 14:59) [57]Код между бегин енд выполнятеся при загрузке процессом.
А выполняется ли он если библиотека грузится вторичным потоком этого процесса?
← →
dms_main © (2004-10-29 15:02) [58]Судя по тому что здесь>
inherited create(false);
a:=a0;
b:=b0;
FreeOnTerminate:=true;
брэкпоинты - и на них выполнение останавливается, то грузит...
← →
Reindeer Moss Eater © (2004-10-29 15:05) [59]Поток грузит библиотеку. И Хендл валидный.
Но это вторичный поток и я не уверен, что в этом случае выполняется код между бегин и енд.
Надо поднимать литературу.
← →
dms_main © (2004-10-29 15:07) [60]так бы и сразу - а то "руки кривые","медицина бессильна".... :-(
подскажите хоть в каком направлении копать.
← →
Reindeer Moss Eater © (2004-10-29 15:09) [61]Экспортируй функцию из DLL и вызывай её явно, а не полагайся на Windows
← →
dms_main © (2004-10-29 15:11) [62]щас попробую..
← →
Digitman © (2004-10-29 15:17) [63]
> dms_main
цитирую тебя :
constructor TMyThread.create(a0,b0:integer);
begin
inherited create(false);
a:=a0;
b:=b0;
FreeOnTerminate:=true;
end;
какого шута ты делаешь
inherited create(false);
!?
ведь доп.поток при этом начинает работать практически немедленно !
на основании чего ты уверен, что строка в конструкторе
a:=a0;
выполнится заведомо раньше, чем строка
c:=a*b;
в теле Execute ?
мозжечком-то пошевели малясь !
← →
Reindeer Moss Eater © (2004-10-29 15:20) [64]Все проще оказалось.
Код между бегин-енд в модуле библиотеки вызывается один раз на весь процесс.
← →
dms_main © (2004-10-29 15:23) [65]
> на основании чего ты уверен, что строка в конструкторе
на основании того что execute вызывается ПОСЛЕ create
кстати от темы опять уходим.....
> Все проще оказалось.
>
> Код между бегин-енд в модуле библиотеки вызывается один
> раз на весь процесс.
и что из этого следует???
← →
Reindeer Moss Eater © (2004-10-29 15:25) [66]и что из этого следует???
То, что кто-то до сих пор с ручника не снялся.
← →
dms_main © (2004-10-29 15:26) [67]
library finer_lib;
uses
SysUtils,windows,
Classes;
type TMyThread = class (TThread)
a:integer;
b:integer;
c:integer;
constructor create(a0,b0:integer);
destructor free;
procedure execute;override;
end;
constructor TMyThread.create(a0,b0:integer);
begin
inherited create(false);
a:=a0;
b:=b0;
FreeOnTerminate:=true;
end;
destructor TMyThread.free;
begin
inherited free;
end;
procedure TMyThread.execute;
var
t:TstringList;
begin
c:=a*b;
t:=TStringList.Create;
t.Add("Result = "+inttostr(c));
t.SaveToFile("c:\result.nfo");
t.Free;
end;
{$R *.RES}
procedure run;stdcall;export;
var
thread:TMyThread;
begin
thread:=TMyThread.create(2,2);
thread.WaitFor;
end;
exports run;
begin
end.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
windows;
var
run : procedure;
handle:THandle;
begin
readln;
@run:=nil;
handle:=LoadLibrary("finer_lib.dll");
if handle>= 32 then
begin
@run:=GetProcAddress(Handle,"run");
if @run <> nil then
run; ;
end;
FreeLibrary(Handle);
writeln("ok");
readln;
readln;
end.
Всем спасибо - все заработало, но всетаки интересен вопрос
- реально ли запустить этот трэд в begin..end библиотеки???
← →
dms_main © (2004-10-29 15:27) [68]
> Reindeer Moss Eater © (29.10.04 15:25) [66]
> и что из этого следует???
>
> То, что кто-то до сих пор с ручника не снялся.
весь день на нервах , так что уж извиняйте.... :-)
← →
Reindeer Moss Eater © (2004-10-29 15:28) [69]Реально.
Один раз за все время существования процесса.
← →
Digitman © (2004-10-29 15:31) [70]
> все заработало
да не будет это работать как положено !
см. [63]
> реально ли запустить этот трэд в begin..end библиотеки
запустить любой код реально !
только вот будет ли он (конкретный твой код) делать то, что от него ожидается - это еще бабушка надвое сказала ...
← →
dms_main © (2004-10-29 15:32) [71]
> То, что кто-то до сих пор с ручника не снялся.
- это точно......
Может объясните????
мне собственно и надо 1 раз , а не 2 и не 10.....
как заставить это работать без экспорта?
← →
dms_main © (2004-10-29 15:33) [72]
> да не будет это работать как положено !
> см. [63]
с экспортом уже работает...
← →
Reindeer Moss Eater © (2004-10-29 15:34) [73]как заставить это работать без экспорта?
Чё, пошлины экспортные давят?
← →
dms_main © (2004-10-29 15:35) [74]
> Чё, пошлины экспортные давят?
ага причем сильно..... :-))
← →
Reindeer Moss Eater © (2004-10-29 15:37) [75]Все это напоминает ток-шоу с приглашенными актерами.
Но актеры эти приглашенные, надо отдать должное здешним спецам по кастингу, иногда просто гениальные попадаются.
Именно гениальные. Снимаю шляпу.
← →
dms_main © (2004-10-29 15:39) [76]А если серьезно?
← →
Reindeer Moss Eater © (2004-10-29 15:39) [77]Так ведь работает уже
← →
Digitman © (2004-10-29 15:40) [78]просто вызови конструктор трэда в теле begin..end библиотеки.
что этому мешает ?
← →
dms_main © (2004-10-29 15:41) [79]
> Так ведь работает уже
с экспортом - да ,а без экспорта - нет.
Я и спросил можно ли без экспорта и если да - то как.
← →
dms_main © (2004-10-29 15:42) [80]
> просто вызови конструктор трэда в теле begin..end библиотеки.
> что этому мешает ?
А я что сделал?
begin
thread:=TMyThread.create(2,2);
thread.WaitFor;
end.
← →
Digitman © (2004-10-29 15:46) [81]
> dms_main © (29.10.04 15:42) [80]
> А я что сделал?
и что ? и продолжаешь утверждать, что управление методу Execute не передается в ходе старта трэда ?
← →
Добрый дядька © (2004-10-29 15:48) [82]>dms_main
Вопрос:
Зачем нужна такая библиотека, которая загружается в приложение, выполняя код один раз, затем висит, занимая ресурсы?
← →
dms_main © (2004-10-29 15:48) [83]ДА именно так
Делаю LoadLibrary - креатиться, а execute не вызывается - из-за этого и вся проблема.
← →
Reindeer Moss Eater © (2004-10-29 15:50) [84]Который поток первый загрузил DLL - того и тапки.
Для него и будет выполнен код между begin/end.
Остальные отдыхают.
← →
dms_main © (2004-10-29 15:53) [85]
> Который поток первый загрузил DLL - того и тапки.
> Для него и будет выполнен код между begin/end.
>
> Остальные отдыхают.
это все понятно - begin..end - вызывается 1 раз
при loadlibrary выполняется begin..end? креатится трэд, прыгает на Waitfor и ждет пока тред завершится - а метод execute в трэде так и не вызывается.... :-(
← →
Digitman © (2004-10-29 15:54) [86]
> dms_main © (29.10.04 15:48) [83]
ерунду не городи.
ставь брейкпойнты на строчках
c:=a*b;
и
thread:=TMyThread.create(2,2);
и лови эти брейкпойнты !
и попробуй только сказать, что ни один из них не "ловится"
← →
Reindeer Moss Eater © (2004-10-29 15:55) [87]при loadlibrary выполняется begin..end?
Чё, еще раз?
Ну давай еще один раз:
Сто раз вызови LoadLibrary - код межу begin end выполнится ровно один раз.
← →
dms_main © (2004-10-29 15:57) [88]
> ерунду не городи.
>
> ставь брейкпойнты на строчках
>
> c:=a*b;
>
> и
>
> thread:=TMyThread.create(2,2);
>
> и лови эти брейкпойнты !
>
> и попробуй только сказать, что ни один из них не "ловится"
именно это и говорю......
И вообще тема разговора именно эта!!!
не веришь - скомпиляй код (сообщение 67) - без экспорта и
через loadlibrary.....
← →
dms_main © (2004-10-29 15:59) [89]
> Чё, еще раз?
> Ну давай еще один раз:
>
> Сто раз вызови LoadLibrary - код межу begin end выполнится
> ровно один раз.
спасибо - это я уже давно понял...... оно и вызывается 1 раз - креатит но execute не вызывает....
← →
Reindeer Moss Eater © (2004-10-29 16:00) [90]креатит но execute не вызывает....
Это потому что хэллоуин на носу.
Подожди до понедельника, будет тебе execute
← →
Digitman © (2004-10-29 16:00) [91]
> без экспорта
да экспорт-то тут причем ?!
хоть он есть, хоть его нет - ну никак это не влияет на сабж !
> не веришь
представь себе - не верю !
и даже проверять не буду ..
и глубоко фиолетово к тому же, КАК грузится твоя ДЛЛ - статически или динамически ..
давай-ка рассказывай, как ты "ловишь" брейкпойнты ..
← →
dms_main © (2004-10-29 16:03) [92]Run>Parameters>Host Application>F9
"MyLib">Reload Symbol Table
← →
dms_main © (2004-10-29 16:18) [93]проверить кстати можно еще проще :
procedure TMyThread.execute;
var
t:TstringList;
begin
c:=a*b;
t:=TStringList.Create;
t.Add("Result = "+inttostr(c));
t.SaveToFile("c:\result.nfo");
t.Free;
end;
в "Экспортном" варианте файл создается, в Loadlibrary - не создается.
← →
Добрый дядька © (2004-10-29 16:20) [94]Все прекрасно работает как в таком виде:
library ThrDll;
uses
Classes,
windows;
type
TMyThread=class(TThread)
FX: String;
protected
procedure Execute; override;
public
constructor Create(const X: String);
end;
{ MyThread }
constructor TMyThread.Create(const X: String);
begin
inherited Create(True);
FX := X;
FreeOnTerminate := True;
Resume;
ResumeThread(Self.Handle);
end;
procedure TMyThread.Execute;
var
i: Integer;
begin
for i := 0 to 10 do
begin
Sleep(200);
Write(FX+#13#10);
end;
Terminate;
end;
procedure DllMain(fdwReason:DWORD);
begin
case fdwReason of
DLL_THREAD_ATTACH: ;
DLL_THREAD_DETACH: ;
DLL_PROCESS_ATTACH:
begin
TMyThread.Create("Hehe");
end;
DLL_PROCESS_DETACH:
begin
end;
end;
end;
begin
DllProc:=@DllMain;
DllMain(DLL_PROCESS_ATTACH);
end.
Вызывающий код:program test;
{$APPTYPE CONSOLE}
uses
Windows;
begin
LoadLibrary("ThrDll.dll");
ReadLn;
end.
так и если убрать DLLMain, а просто вставить в DLL всекцию после beginTMyThread.CrReate("Hehe");
← →
Digitman © (2004-10-29 16:21) [95]
> dms_main © (29.10.04 16:03) [92]
в Д5 в настройках Host Application нет никаких Reload Symbol Table
это раз.
второе.
ты стартовал отладку ДЛЛ, поймал брейкпойнт на строчке
thread:=TMyThread.create(2,2);
почему не прошел конструктор пошагово ?
ведь если BeginThread() выполнилась успешно, то признаков фактического старта трэда более чем достаточно !
это и ненулевой ThreadId и ненулевой Handle ... То что Handle ненулевой - это уже гарантировано, иначе WaitFor немедленно возвратил бы управление, чего, как ты говоришь, не наблюдается у тебя .. .
а если так, то рано или поздно процедура Execute обязана была бы получить управление ! Ведь поточная ф-ция успешно стартовала !
← →
Добрый дядька © (2004-10-29 16:21) [96]Сорри, строка ResumeThread в конструкторе не нужна.
← →
dms_main © (2004-10-29 16:25) [97]I>
> Все прекрасно работает как в таком виде:
как было так и есть...<
← →
Добрый дядька © (2004-10-29 16:25) [98]А вот ошибка в твоем коде:
constructor TMyThread.create(a0,b0:integer);
begin
inherited create(false);
a:=a0;
b:=b0;
FreeOnTerminate:=true;
end;
Это первая.{$R *.RES}
var
thread:TMyThread;
begin
thread:=TMyThread.create(2,2);
thread.WaitFor;
end.
Это вторая.
← →
dms_main © (2004-10-29 16:26) [99]
>
> {$R *.RES}
> var
> thread:TMyThread;
> begin
> thread:=TMyThread.create(2,2);
> thread.WaitFor;
> end.
>
> Это вторая.
а если мне надо дождаться его завершения?
← →
Reindeer Moss Eater © (2004-10-29 16:27) [100]Добрый дядька © (29.10.04 16:20) [94]
Все прекрасно работает как в таком виде:
Если делать это в одном потоке.
← →
Добрый дядька © (2004-10-29 16:28) [101]Вторая ошибка потому, что
FreeOnTerminate:=true;
Не может использоваться сthread.WaitFor;
← →
Добрый дядька © (2004-10-29 16:29) [102]>Reindeer Moss Eater © (29.10.04 16:27)
Если делать это в одном потоке.
По условиям задачи разве не это нужно?
← →
Reindeer Moss Eater © (2004-10-29 16:29) [103]Добрый дядька © (29.10.04 16:28) [101]
Это не объясняет феномен невызова Execute
← →
Reindeer Moss Eater © (2004-10-29 16:30) [104]По условиям задачи разве не это нужно?
не это нужно по условиям задачи
← →
Добрый дядька © (2004-10-29 16:30) [105]В случае, если нужно дождаться завершения потока, то используется FreeOnTerminate := True,
затем
WaitFor
Free
Это из-за особенностей реализации TThread
← →
Reindeer Moss Eater © (2004-10-29 16:31) [106]Добрый дядька © (29.10.04 16:30) [105]
Это не объясняет феномен невызова Execute
← →
dms_main © (2004-10-29 16:31) [107]Digitman ©
сорри забыл дописать перед пелодом ctrl+alt+m
← →
Digitman © (2004-10-29 16:33) [108]
> dms_main © (29.10.04 16:26) [99]
> а если мне надо дождаться его завершения?
да ёшкин кот !!
мы тут о чем говорим ? о твоем утверждении, что Execute у тебя якобы не вызывается !
какого рожна ты стрелки переводишь на не имеющее отношения к проблеме строчку ? мало ли что там у тебя торчит в коде следом за конструктором потока ! ты стартовал поток как not suspended, исключения ты не получил при вызове конструктора, значит Execute обязан был получить управление ! И абсолютно неважно, что у тебя там стоит следующей строчкой ! Правильность логики вызова WaitFor в данноим контексте - это совершенно иной вопрос !
← →
Добрый дядька © (2004-10-29 16:35) [109][103] Reindeer Moss Eater © (29.10.04 16:29)
Добрый дядька © (29.10.04 16:28) [101]
Это не объясняет феномен невызова Execute
Именно объясняет.
Поток создается с Inherited(False), поточная функция просто не успевает начать выполняться.
← →
dms_main © (2004-10-29 16:35) [110]
> мы тут о чем говорим ? о твоем утверждении, что Execute
> у тебя якобы не вызывается !
смотри 93 мессагу
← →
Digitman © (2004-10-29 16:36) [111]
> ctrl+alt+m
ЭТО к чему ? опять стрелки переводишь ?
какое отношение состояние открытости IDE-окна имеет к проблеме ?
← →
dms_main © (2004-10-29 16:37) [112]
>
> ЭТО к чему ? опять стрелки переводишь ?
> какое отношение состояние открытости IDE-окна имеет к проблеме
> ?
открывается окно загруженных модулей - так в своем делаешь Reload Symbol Table
← →
Reindeer Moss Eater © (2004-10-29 16:40) [113]Поток создается с Inherited(False), поточная функция просто не успевает начать выполняться.
И что же ей мешает?
← →
dms_main © (2004-10-29 16:41) [114]
> Поток создается с Inherited(False), поточная функция просто
> не успевает начать выполняться.
>
> И что же ей мешает?
Да же если create(true) а потом resume - толку нет. :-(
← →
Добрый дядька © (2004-10-29 16:42) [115]>Reindeer Moss Eater © (29.10.04 16:40)
И что же ей мешает?
Я думаю, возникающий Exception, в результате чего процесс успешно терминируется системой вместе с вновь созданным(или не успевшим создаться) потоком.
← →
Добрый дядька © (2004-10-29 16:43) [116]>dms_main © (29.10.04 16:41)
Ты мой код попробовал? Выполняется?
← →
Reindeer Moss Eater © (2004-10-29 16:44) [117]в результате чего процесс успешно терминируется
Что-то мы про это не слышали от приглашенного актера
← →
dms_main © (2004-10-29 16:44) [118]
> Добрый дядька © (29.10.04 16:43) [116]
> >dms_main © (29.10.04 16:41)
>
> Ты мой код попробовал? Выполняется?
выполняется create, а execute - нет.
← →
Добрый дядька © (2004-10-29 16:45) [119]>Reindeer Moss Eater © (29.10.04 16:44)
Что-то мы про это не слышали от приглашенного актера
А что же вы слышали от приглашенного актера? что его консольное приложение стартует и тут же заканчивается? Так на это можно было не обратить внимание.
← →
Добрый дядька © (2004-10-29 16:46) [120]>dms_main © (29.10.04 16:44)
Т.е. ты в точности создал проект с кодом библиотеки и вызовом?
← →
dms_main © (2004-10-29 16:46) [121]
> >Reindeer Moss Eater © (29.10.04 16:40)
>
> И что же ей мешает?
>
> Я думаю, возникающий Exception, в результате чего процесс
> успешно терминируется системой вместе с вновь созданным(или
> не успевшим создаться) потоком.
Странно - никаких исключений и ошибок я не наблюдаю......
← →
Reindeer Moss Eater © (2004-10-29 16:47) [122]Добрый дядька ©
Он в IDE его отлаживает если помнишь.
← →
dms_main © (2004-10-29 16:48) [123]> Добрый дядька - нет исправил свой в точности с указаниями
(зачем смысл то тотже)
← →
Добрый дядька © (2004-10-29 16:50) [124]>dms_main © (29.10.04 16:48)
(зачем смысл то тотже)
А ты не думаешь, что у тебя может быть проблема в коде, который ты используешь? Например, при работе с файлом?
← →
dms_main © (2004-10-29 16:50) [125]Мастера - насчет отладки - в execute создается файл - нету этого файла - несоздается он > execute не выполняется.
← →
dms_main © (2004-10-29 16:51) [126]В console Application тотже код работает без проблем.
← →
Reindeer Moss Eater © (2004-10-29 16:54) [127]Парень, сколько раз можно повторять, что у тебя не создается экземпляр, потому и нет execute.
А в отладчике есть создание потому что IDE загружает библиотеку первая.
← →
dms_main © (2004-10-29 16:57) [128]
> Reindeer Moss Eater © (29.10.04 16:54) [127]
> Парень, сколько раз можно повторять, что у тебя не создается
> экземпляр, потому и нет execute.
>
> А в отладчике есть создание потому что IDE загружает библиотеку
> первая.
ok - тоесть без экспорта работать небудет?(файла то создаваемого нет)
← →
Digitman © (2004-10-29 16:59) [129]я, кажись, начинаю понимать, в чем дело ..
это, видимо, известный глюк на стыке встроенного дебаггера и ВинХРю без апдейта ...
т.е. Execute-то как раз выполняется, но вот из-за глюка дебаггер не может отработать брэйкпойнт в теле поточной ф-ции
но даже если так, то MessageBox (ПЕРВОЙ же строчкой после begin в Execute) обязан зафиксировать факт успешного старта поточной ф-ции... если, конечно же, не умудриться напортачить еще и с параметрами MessageBox..
← →
dms_main © (2004-10-29 17:04) [130]> Digitman ©
винда ХР со всеми патчами,D7 без мудрежа дэббагит,
нету ни файла ни месседж бокса ни меесадж бипа.
← →
Digitman © (2004-10-29 17:09) [131]
> dms_main © (29.10.04 17:04) [130]
да ну не верю я !
ты что-то существенное скрываешь, то что упорно не приводишь в примерах своего кода ..
почему ты до сих пор не оттрассировал пошагово тело конструктора TThread ?
← →
dms_main © (2004-10-29 17:15) [132]вот те другой мой код в котором таже беда - невижу смысла выкладывать 14к кода если в 0,7к таже беда:
library finer_lib;
uses
SysUtils,windows,
Classes;
type TMyThread = class (TThread)
a:integer;
b:integer;
c:integer;
constructor create(a0,b0:integer);
destructor free;
procedure execute;override;
end;
constructor TMyThread.create(a0,b0:integer);
begin
inherited create(true);
a:=a0;
b:=b0;
// FreeOnTerminate:=true;
resume;
end;
destructor TMyThread.free;
begin
inherited free;
end;
procedure TMyThread.execute;
var
t:TstringList;
begin
c:=a*b;
t:=TStringList.Create;
t.Add("Result = "+inttostr(c));
t.SaveToFile("c:\result.nfo");
t.Free;
end;
{$R *.RES}
var
thread:TMyThread;
begin
delete
thread:=TMyThread.create(2,2);
thread.WaitFor;
end.
← →
Добрый дядька © (2004-10-29 17:16) [133]Так тоже дебаггер не заходит в поточную функцию?
library ThrDll;
uses
windows;
type
TParm=record
X,Y: Integer;
end;
var
Parm: TParm;
ThreadId: THandle;
procedure ThreadFunc(aParm: Pointer); cdecl;
var
i: Integer;
begin
for i := 0 to TParm(aParm^).X do
begin
Write("Test"+#13#10);
end;
end;
begin
Parm.X := 2;
Parm.Y := 2;
CreateThread(nil,0,@ThreadFunc,@Parm,0,ThreadId);
end.
← →
Reindeer Moss Eater © (2004-10-29 17:18) [134]Код приглашенного актера прекрасно работает в консольном приложении (читай - в однопоточном) - давайте верить в это.
В многопоточном не работает как надо. - давайте тоже верить в это.
Значит где трабл зарыт?
Правильно. В особенности парочки DLL + вторичный поток.
Не понимаю, как можно в течении 130 постов обсуждать очевидное.
← →
dms_main © (2004-10-29 17:18) [135]Добрый дядька © >
это - совершенно другая песня здесь заходит.
← →
Digitman © (2004-10-29 17:19) [136]
> dms_main © (29.10.04 17:15) [132]
и долго ты еще будешь постить сюда один и тот же код в разных вариациях ?
я тебе вопрос задал - ЧТО показала пошаговая трассировка TThread.Create() ?
← →
dms_main © (2004-10-29 17:20) [137]Reindeer Moss Eater © > несогласен только с одним - "приглашенный актер" интересно это к чему? :-(
← →
Reindeer Moss Eater © (2004-10-29 17:21) [138]ЧТО показала пошаговая трассировка TThread.Create() ?
Ничего полезного она не покажет.
Отладчик туда зайдет, потому что либа бкдет все же загружена.
Но вторичный поток загрузив либу, не заставит отладчик зайти туда.
← →
dms_main © (2004-10-29 17:21) [139]
> Digitman ©
весь код который в create выполнился, в execute не заходит.
← →
Reindeer Moss Eater © (2004-10-29 17:24) [140]Reindeer Moss Eater © > несогласен только с одним - "приглашенный актер" интересно это к чему? :-(
Потому что программер на форуме решает реальные проблемы, а приглашенный актер играет роль.
← →
Digitman © (2004-10-29 17:25) [141]
> Reindeer Moss Eater © (29.10.04 17:18) [134]
что-то я тебя не понял ..
какая разница, откуда будет вызвана в дан.случае LoadLibrary - из основного или доп.трэда хост-процесса ? та же CreateThread в конечном итоге вызывается, что мешает ее успешному выполнению, даже если вызвана она из доп.трэда ?
проблема эта становится актуальной в иных случаях, не связанных с конструированием трэда, но об этом пока речи и не идет, кажется ...
или ты намекаешь на то, что до CreateThread даже дело не доходит ? но в Д5, по кр.мере, обязано доходить !
← →
dms_main © (2004-10-29 17:26) [142]
> Reindeer Moss Eater ©
то есть получается я от нефиг делать тут весь день торчу ? :-(
> Потому что программер на форуме решает реальные проблемы
и трабла моя вымышлена?
← →
Reindeer Moss Eater © (2004-10-29 17:28) [143]Разница такая.
Мы ставим BP.
И мы попадем на эту BP.
Но это не та нить, которую мы отлаживаем.
У него нет следов файла, который должен появиться в результате загрузки либы вторичным потоком.
Точка останова есть, и мы туда попадаем.
Но только не тогда, когда вторичный поток делает LoadLobrary
← →
dms_main © (2004-10-29 17:30) [144]
> Но только не тогда, когда вторичный поток делает LoadLobrary
Я это все давно понял - можно не повторяться.
Лечиться это или нет - вот в чем вопрос.
← →
dms_main © (2004-10-29 17:30) [145]
> Но только не тогда, когда вторичный поток делает LoadLobrary
Я это все давно понял - можно не повторяться.
Лечиться это или нет - вот в чем вопрос.
← →
Reindeer Moss Eater © (2004-10-29 17:32) [146]Лечиться это или нет - вот в чем вопрос.
Устал я. Домой иду.
← →
Digitman © (2004-10-29 17:35) [147]
> Reindeer Moss Eater © (29.10.04 17:21) [138]
с какой стати отладчик автоматом загрузит ДЛЛ, если она в хост-приложении грузится искл-но динамически ? и если никаких Reload Symbol Table и иже с ним сомнительных фич не задействовать явно ?
← →
Добрый дядька © (2004-10-29 17:37) [148]>dms_main © (29.10.04 17:30)
WAitFor убери. Совсем.
← →
Reindeer Moss Eater © (2004-10-29 17:41) [149]с какой стати отладчик автоматом загрузит ДЛЛ, если она в хост-приложении грузится искл-но динамически ?
Динамически. Да.
Но не из единственного потока.
какая разница, откуда будет вызвана в дан.случае LoadLibrary - из основного или доп.трэда хост-процесса ?
Никакой разницы нет. Можно из основного, можно из вторичного.
Разница есть какой поток делает это первым в процессе.
Потому что у него код создания потока, создающего файлы привязан к блоку begin/end библиотеки.
А блок этот вызывается один раз за весть процесс сколько бы ни вызывали LoadLibrary в этом процессе.
А актер экспортировать и явно вызывать из библиотеки ничего не хочет, бо пошлины экспортные ему мешают.
← →
Reindeer Moss Eater © (2004-10-29 17:52) [150]И вообще не понятно, откуда берутся параметры для конструктора того потока, если его запуск заточен под автоматическое выполнение кода между begin/end библиотеки при простой загрузке библиотеки.
Получается, что они вообще хардкодед.
← →
Defunct © (2004-10-29 19:07) [151]Ну и развели..
Надо было сказать:
> Лечиться это или нет - вот в чем вопрос.
Лечится только в военном госпитале.
← →
Reindeer Moss Eater © (2004-11-01 10:40) [152]Что бы "работало" без экспорта
library lib;
uses Windows;
{$R *.res}
procedure DllProcedure(AReason : integer);
begin
case AReason of
DLL_PROCESS_ATTACH,
DLL_THREAD_ATTACH : begin
//Создание экземпляров TThread
....
end;
DLL_PROCESS_DETACH :;
DLL_THREAD_DETACH :;
end;
end;
begin
DllProc := DllProcedure;
DllProc(DLL_PROCESS_ATTACH);
end.
← →
Digitman © (2004-11-01 11:50) [153]
> Reindeer Moss Eater © (29.10.04 17:41) [149]
DLL_THREAD_ATTACH здесь к делу никоим образом не относится
как только любой трэд процесса в самый первый раз будет грузить ДЛЛ (явно или неявно), системой будет вызвана DllEntryPoint(DLL_PROCESS_ATTACH), что в конечном счете должно привести к передаче управления в блок begin..end библиотеки, где у автора вызывается конструктор TMyThread.Create (он и вызывается в действительности - автор это подтверждает) .. если в ходе работы конструктора не возникло исключений, то поточная ф-ция обязана стартовать и вызвать при этом Execute, и брейкпойнт в самом начале тела Execute ну просто обязан быть пойманным отладчиком ..
← →
DiamondShark © (2004-11-01 12:41) [154]Балин...
Любите хелп -- источник знаний:
During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process.
← →
Reindeer Moss Eater © (2004-11-01 12:43) [155]Он (автор) хочет, что бы бегин/енд выполнялся при LoadLibrary из любого потока хост приложения.
Он не хочет ничего экспортировать, но хочет автоматического выполнения кода при загрузке.
← →
Reindeer Moss Eater © (2004-11-01 12:57) [156]DiamondShark ©
Любите источник знаний целиком и до конца.
Все это касается статического импорта библиотеки.
Если импорт динамический, то вторичному потоку ничто не помешает ни выполняться, ни самому грузить dll первее главного треда
← →
Digitman © (2004-11-01 12:57) [157]
> Reindeer Moss Eater © (01.11.04 12:43) [155]
я ОДНОГО не понял - автор утверждает, что ВР в теле Execute он ВООБЩЕ не ловит в ходе самого первого обращения к ДЛЛ ... хотя тело конструктора хотя бы однократно получает управление ...
этого быть не может - рано или поздно поточная ф-ция все равно стартует
> DiamondShark © (01.11.04 12:41) [154]
ну и что ? рано или поздно ВР должна сработать !
← →
DiamondShark © (2004-11-01 13:04) [158]
> Reindeer Moss Eater © (01.11.04 12:57) [156]
Это ты к чему?
> Digitman © (01.11.04 12:57) [157]
> ну и что ? рано или поздно ВР должна сработать !
Не-а. У него там WaitFor стоит.
← →
DiamondShark © (2004-11-01 13:14) [159]Объясняю.
Вызываем LoadLidrary, LoadLidrary не возвращается, пока не отработает DLL entry point.
В DLL entry point создаётся поток, который будет подвешен, пока не завершится DLL entry point.
К контексте DLL entry point вызывается поток.WaitFor, которая не вернётся, пока не закончится поток, который не запустится пока не закончится DLL entry point, которая не закончится пока не вернётся WaitFor... в доме который построил Джек.
Если убрать WaitFor, то поток начнёт работь сразу, как вернётся DLL entry point. Тут, правда автором заботливо подложены другие грабли в виде FreeLibrary сразу после LoadLibrary.
← →
Юрий Зотов © (2004-11-01 13:22) [160]Всю ветку читать не стал - слишком длинная. Поэтому просто скажу, в чем тут, похоже, дело и сорри, если повторю кого-то или скажу "не в кассу".
Проблема XP-DLL-отладчик известная (хоть в однопоточном, хоть в многопоточном приложении). По какой-то причине отладчик не подгружает отладочную символьную информацию из DLL и поэтому брейкпойнты в DLL не срабатывают (хотя код работает). Лечится это либо установкой эксперта IDE (встречал в сети, но где - не помню), либо так.
1. В DLL сразу после главного begin пишем любой MesssageBox -что угодно, лишь бы тормознуть программу.
2. Когда этот MessageBox появится, переключаемся в Delphi, жмем Ctrl-Alt-M, в появившемся окне (слева внизу) находим свою DLL, жмакаем по ней правой кнопкой мыши и выбираем Reload Symbol Table. Если все прошло ОК, то справа увидим, что отладочная информация подгрузилась.
3. В MessageBox жмем OK - теперь брейкпойнты должны работать.
← →
DiamondShark © (2004-11-01 13:24) [161]Да нет там никаких проблем икспи-отладчик...
← →
Digitman © (2004-11-01 13:32) [162]
> DiamondShark © (01.11.04 13:04) [158]
> Не-а. У него там WaitFor стоит.
WaitFor в таком контексте [см. 154] д.б. бы вызвать дэдлок, однако автор ничего не говорит на тему якобы "зависания" приложения, вызывающего ДЛЛ по LoadLibrary.
← →
DiamondShark © (2004-11-01 13:40) [163]
> Digitman © (01.11.04 13:32) [162]
Мало ли что автор не говорит, он свой реальный код тоже долго не говорил.
Тем не менее, его код на LoadLibrary именно зависает.
← →
Reindeer Moss Eater © (2004-11-01 13:50) [164]Тем не менее, его код на LoadLibrary именно зависает.
А еще он говорит, что в консольном приложении все нормально.
И никакой waitfor ему не помеха.
← →
Digitman © (2004-11-01 13:58) [165]что-то подустал я тут из пустого в порожнее переливать ..
автор давно уже ни мычит ни телится
← →
DiamondShark © (2004-11-01 14:28) [166]
> Reindeer Moss Eater © (01.11.04 13:50) [164]
> А еще он говорит, что в консольном приложении все нормально.
> И никакой waitfor ему не помеха.
А мы на слово никому не верим.
Проблема воспроизведена, причина описана, пути решения намечены.
Ждём-с реакции автора...
← →
dms_main © (2004-11-02 22:11) [167]Господа! Все оказалось намного проще....
Execute выполняется после begin...end. библиотеки, правда есть одно но - но это не важно.
Решается так :
Создаем еще один класс потока,
create его ставим в begin...end. библиотеки, на его execute забиваем create того кода что был в begin ... end. библиотеки -
и все у нас работает прекрасно.
Спасибо всем кто принял участие в решении вопроса.....
Страницы: 1 2 3 4 5 вся ветка
Форум: "Основная";
Текущий архив: 2004.11.14;
Скачать: [xml.tar.bz2];
Память: 0.9 MB
Время: 0.062 c