Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.09.16;
Скачать: CL | DM;

Вниз

У меня возникает ошибка при вызове процедуры из DLL внутри потока   Найти похожие ветки 

 
Kent ©   (2002-09-04 16:33) [0]

Привет, всем !
Прошу помощи, позарез надо решить задачу.
У меня возникает ошибка при вызове процедуры из DLL внутри потока, поток прямой наследник класса TThread, вот кусок кода:


procedure TSPDLLThread.Execute;
var FarProc: procedure (LogFileName,ResultPath,Exclusions: PChar;
UUCounting,LTCounting,DoBackup: Boolean;
BackupName: PChar; EraseLog: Boolean);
begin
OnTerminate:=Form1.ThreadDone;
FreeOnTerminate:=True;
if WaitForSingleObject(SPThreadMutex,INFINITE)=WAIT_OBJECT_0 then
begin
FDLLHandle:=LoadLibrary(PChar(FDLLName));
if FDLLHandle<>0 then
begin
@FarProc:=GetProcAddress(FDLLHandle,PChar(FFarProcName));
if @FarProc<>nil then
begin
//Вот если вызов функции FarProc не выполнять, все ОК
//Иначе Access Violation, причем если вызов выполнять
//в контексте основной программы, то все отлично
//Но процедура долгая - нужен параллельный поток
FarProс(FLogFileName,FResultPath,FExclusions,
FUUCounting,FLTCounting,FDoBackup,
FBackupName,FEraseLog);
end;
FreeLibrary(FDLLHandle);
end;
end;
ReleaseMutex(SPThreadMutex);
end;

В чем проблема - никак не доеду :( !!!!
Помогите PLS !!!!


 
NailS ©   (2002-09-04 17:06) [1]

А как процедура в длл объявлена?


 
Виктор Щербаков ©   (2002-09-04 17:11) [2]

Здесь вроде всё ОК. Наверно причина возникновеня ошибки в коде FarProc. И еще, интересно, почему отсутствует соглашение овызове в объявлении функции? Так и задумано?


 
Kent ©   (2002-09-04 17:21) [3]

В FarProc, когда я ее вызываю из тела основной программы, ошибок не вылезает вообще все четко, но сама процедура ведет разбор и анализ лога, довольно долгая процедура. Вот и понадобилось ее запихать в фоновый процесс с низким приоритетом, а то создается впечатление, что программа подвисла :(.

Процедура в DLL объявлена как:

procedure ParseLog(StatLogName: PChar;
ResultPath: PChar;
Excs: PChar;
UUserCount: Boolean;
LTCounting: Boolean;
DoBackup:Boolean;
BackupName: PChar;
EraseLog: Boolean);

По поводу соглашений о вызове, как говорится, поподробнее .. :), если нетрудно :), как правильней здесь поступить?


 
Виктор Щербаков ©   (2002-09-04 17:25) [4]


> как правильней здесь поступить

Ну это не принципиально. Главное чтобы они совпадали. Обычно пишут и там и тут stdcall


 
NailS ©   (2002-09-04 17:28) [5]

А мьютекс зачем?
И код процедуры в студию.


 
Kent ©   (2002-09-04 17:32) [6]

Да, вот еще интересный факт !!! Процедура начинает работу, в процессе выполнения там, внутри процедуры, создаются и записываются файлы, так вот файлы она создает, даже впечатление, что что-то обрабатывает... но , Access Violation at address bla-bla-bla etc...и файлы по 0 кб. Я попробую дома еще раз оттрассировать процедуру, может быть возникает ошибка при работе с файлами ... хотя если в теле программы-то делать .. не возникает. Во какая заморока ... :))


 
Kent ©   (2002-09-04 17:36) [7]

А мьютекс необходим для того, чтобы основная программа ждала окончания работы потока по WaitForSingleObject (чтобы не было эффекта подвисания). А то она накидывается на еще не обработанные файлы и выводит не полную информацию. Вот как !! А код какой процедуры в студию ???


 
NailS ©   (2002-09-04 17:47) [8]


> А то она накидывается на еще не обработанные файлы и выводит
> не полную информацию. Вот как

Хитро.

Процедуру, которая в длл файлы обрабатывает, и внутри которой ошибка происходит.


 
Digitman ©   (2002-09-04 18:10) [9]

>Kent

Как раз и будет этот самый "эффект подвисания" ! ты ж в осн.потоке ждешь некоторое время этот мьютекс, не реагируя никак на оконные сообщения... Тогда уж MsgWaitForMultipleObjects нужно использовать в цикле : и мьютекс дождешься и оконные сообщения обрабатывать будешь успевать)

Только мьютекс здесь лишний - для MsgWaitForMultipleObjects достаточно хэндла код.потока, завершения которого ты ожидаешь. Как только он завершится, ф-ция "просигналит" точно также, как при ожидании освобождения мьютекса


 
Kent ©   (2002-09-05 08:47) [10]

Да вот я тоже так думал, что будет с WaitForSingleObject "висяк", ан нет - делаю поток, пока основная прога ждет освобождения мьютекса, я свободно могу таскать ее за "шиворот", она реагирует на меню....
А мьютекс мне здесь просто удобно использовать: дело в том, что к этим файлам, которые обрабатываются одним потоком, может обратиться другой поток, формирующий на основании данных из файлов контент HTML-страницы. Вот и передается у меня мьютекс, как маркер, от одного потока к другому, чтобы они не накладывались по времени ....

А процедуру я не смогу сюда поместить - она просто здоровая очень, длинные строки, боюсь что читать будет очень сложно...


 
Kent ©   (2002-09-05 09:58) [11]

Похоже все таки где-то некорректно выполняются операции во внешней процедуре. Сейчас сделал тестовую библиотеку с одной функцией, которая делает строке UpperCase ... и все работает 8).
У меня уже крыша скоро съедет. Буду препарировать свой код. О результате сообщу ....
Огромное спасибо всем кто откликнулся !!!
P.S. Какое счастье иметь выделенный канал :))), хоть с братьями по разуми пообщаться не дергаясь можно . :))


 
Digitman ©   (2002-09-05 10:59) [12]

The WaitForSingleObject function returns when one of the following occurs:

· The specified object is in the signaled state.
· The time-out interval elapses.

А если WaitForSingleObject вызвана в осн.потоке, таймаут = INFINITE и доп.поток не освобождает долгое время мьютекс ? Каким же образом осн.поток у тебя будет обрабатывать оконные сообщения, если он в дан.момент ждет завершения ф-ции WaitForSingleObject, которая "зависла" на неопред.время ?


 
Kent ©   (2002-09-05 11:00) [13]

А вот и свежие блинчики !!! Нашел трабл !!!
Короче, не вдаваясь в подробности заменил все свойства метода, определенные как PChar на string. (Мне в поток надо было передать имя файла для обработки, я передавал его как PChar).
Работает !! Такое впечатление, что либо я что-то делал неправильно, либо конструктор потока не умеет правильно работать с передачей параметров в PChar, может инициализация или освобождение ресурсов некорректно проходит.

P.S. Ну вот теперь хоть сам могу на вопросы поотвечать пойти, а то все задаю и задаю :)))


 
Kent ©   (2002-09-05 11:03) [14]

А вот это надо спросить у того кто функцию WaitForSingleObject писал :))
А точно ли на 100% что окно, ожидая результата WIAT_OBJECT_0, перестает обрабатывать сообщения и вызывать WndProc ??


 
Виктор Щербаков ©   (2002-09-05 11:07) [15]


> А точно ли на 100% что окно, ожидая результата WIAT_OBJECT_0,
> перестает обрабатывать сообщения и вызывать WndProc ??

А каким образом ты попадешь в цикл обработки сообщений, если поток находится в состоянии ожидания?


 
Старый Паскалист   (2002-09-05 11:08) [16]

>Kent ©
>А точно ли на 100% что окно, ожидая результата WIAT_OBJECT_0, >перестает обрабатывать сообщения и вызывать WndProc.

Абсолютно точно.
Когда поток вызывает ф-ю Wait..., процессор просто перестаёт выделять ему время.



 
Kent ©   (2002-09-05 11:32) [17]


> Как раз и будет этот самый "эффект подвисания" ! ты ж в
> осн.потоке ждешь некоторое время этот мьютекс, не реагируя
> никак на оконные сообщения... Тогда уж MsgWaitForMultipleObjects
> нужно использовать в цикле : и мьютекс дождешься и оконные
> сообщения обрабатывать будешь успевать)


Приношу свои извинения, абсолютно точно ваше замечание, это я чудило тряпошное, я просто заремил функцию WaitForSingleObject в основном контексте... и удивлялся, наивный :))
А можно в двух словах попросить объяснений, как тогда поступить чтобы не "вешать" основной поток ????


 
Виктор Щербаков ©   (2002-09-05 11:45) [18]


> А можно в двух словах попросить объяснений, как тогда поступить
> чтобы не "вешать" основной поток ????

Например, при окончании работы второго потока посылать сообщение в одно из окон основного потока. Кстати, эти сообщения можно посылать и чаще, тем самым получишь возможность отображать процесс работы. Еще, посмотри TThread.OnTerminate.


 
Старый Паскалист   (2002-09-05 11:46) [19]

Вообще-то объекты синхронизации по своей идее предназначены для защиты участков кода, которые только по случайности могут выполняться одновременно. И обычно стараются сделать защищённые участки как можно более быстрыми.

У тебя же нет никакой случайности. Поэтому нужно просто как-то по другому организовать логику.
Например, по окончании работы поток шлёт сообщение или устанавливает какой-то флаг, что к данным обращаться можно.


 
Kent ©   (2002-09-05 11:49) [20]

Да, пожалуй буду по Create"у потока устанавливать флаг, а в OnTerminate сбрасывать !!!

Огромное спасибо всем, кто помогал !

P.S. Кстати, я сейчас еще одну темку подкину, это просто вопрос очень занятный, если будет желание, посмотрите ...


 
Digitman ©   (2002-09-05 11:54) [21]

>Kent

Например , так :

var
Msg: TMsg;
...

while True do
case MsgWaitForMultipleObjects(1, hMutex, False, 1000, QS_ALLINPUT) of
WAIT_OBJECT_0: break; // сигнал "мьютекс свободен"
WAIT_OBJECT_0 + 1: Application.ProcessMessages; //в очередях окон осн.потока процесса есть необработанные сообщения - обработать их
WAIT_ABANDONED: break; // объект-мьютекс больше не существует
WAIT_TIMEOUT: continue; // таймаут ожидания исчерпан - можно еще подождать, если требуется, а можно и выйти из цикла по некоему условию, например, превышено знач-е сч-ка таймаутов ожидания событий




Страницы: 1 вся ветка

Текущий архив: 2002.09.16;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.011 c
3-50660
mas_alexey
2002-08-22 18:56
2002.09.16
BDE


14-50978
Soft
2002-08-22 15:23
2002.09.16
Сайт накопитель по AI


4-51031
vixic
2002-07-26 10:20
2002.09.16
DLL + API = MainMenu


14-50927
nikolo
2002-08-21 10:50
2002.09.16
БД улиц Москвы


7-51001
Gogos
2002-07-07 11:53
2002.09.16
Как можно изменить текст «Приветствие» при старте Win XP?