Форум: "Основная";
Текущий архив: 2002.09.16;
Скачать: [xml.tar.bz2];
Вниз
У меня возникает ошибка при вызове процедуры из 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;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.007 c