Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Thread creation error


Автор: Unregistered 6.7.2004, 01:53
Программа в отдельном потоке опрашивает устройство через ком-порт. Опрос идет непрерывно, круглосуточно. Если в обмене происходит какой-то сбой, то поток убивается и создается по новой. Отработала прога уже больше полугода и вот какая проблема случилась: в одно прекрасное утро обмен прекратился. Прога выдала ошибку "Thread creation error. Подсоединенное к системе устройство не работает". После перезагрузки системы все опять заработало. В проге не стоит проверка на корректность создания потока, отсюда и ошибка вылетает-это понятно. Непонятны причины по которым система не может создать поток. Может кто-нибудь объяснить? Спасибо.

Автор: <Spawn> 6.7.2004, 08:03
для этого желательно бы код посмотреть его содзадия или самому написать обработчик ошибок примерно следующего содержания:

Код
ShowMessage(SysErrorMessage(GetLastError))


Если это была системная ошибка, а не генерируемая Дельфийским наследником Exception.

Автор: Петрович 6.7.2004, 11:49
А какая система?
Слышал (сам не проверял), что Win9x при создании+уничтожении потока безвозвратно теряет часть системных ресурсов. Причем, в источнике информации было даже сказанно сколько и каких, но к сожалению, не помню где он этот источник.
Если это так, то при очень длительной работе системы без перезагрузки, если какой-либо из процессов периодически создает и удаляет потоки, то однажды это ему не удасться sad.gif. И поможет только перезагрузка OS.
У тебя очень похоже на это.

Автор: _hunter 6.7.2004, 16:14
насколько я слышал smile.gif ресурсы теряются если поток создать спящим, а потом, не запуская, убить

Автор: Unregistered 7.7.2004, 03:23
На 98-ю это очень похоже, но мы специально для этой программы выделили машину под w2kprof.
Хотя никто не исключал и там такие-же косяки. :(
Код создания прост до безобразия:

constructor TCommThread.Create(CommPort:THandle;const Request:array of byte;RequestSize:DWORD);
var i:integer;
begin
inherited Create(true);
AbnormalTerminate:=0;
UserCancel:=false;
CommHandle:=CommPort;
SetCommMask(CommHandle,EV_RXCHAR);
OVRL.Internal:=0;
OVRL.InternalHigh:=0;
OVRL.Offset:=0;
OVRL.OffsetHigh:=0;
OVRL.hEvent:=CreateEvent(nil,false,false,nil);//overlapp для WaitCommEvent
SetLength(arrRequest,RequestSize);
For i:=0 to RequestSize-1 do
arrRequest[i]:=Request[i];
WriteLog('Start at '+DateTimeToStr(Now));
Resume;
end;

OVRL - структура TOverlapped объявленная глобально. С ней работает только один экземпляр потока TCommThread.

Обработчик я написал по совету Spawn-а, но, блин, еще пол-года ждать? :)

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

Автор: Петрович 7.7.2004, 08:10
Цитата
одна из них глюкнула, остальные продолжали работать

Может остальные в этот момент просто не пыталсь пересоздать поток?
Цитата
Код
OVRL.hEvent:=CreateEvent(nil,false,false,nil);//overlapp для WaitCommEvent

А при уничтожении потока (в Destroy) ты не забываешь сделать CloseHandle для OVRL.hEvent ?
И еще, arrRequest где объявлена ?

Автор: _hunter 7.7.2004, 15:46
блин я ж про это и писал:
__fastcall TThread(bool CreateSuspended);

поэтому должно быть inherited Create(false);
( это при условии что поток у тебя никто специально не запускает ( я этот кусок не увидел ) и твой TCommThread -- наследник TThread' a ( этого я тоже не увидел ) )

Автор: Петрович 7.7.2004, 21:39
Цитата
это при условии что поток у тебя никто специально не запускает ( я этот кусок не увидел ) и твой TCommThread -- наследник TThread' a ( этого я тоже не увидел ) )

Как это не увидел? А как ты думаешь, что делает Resume в конце приведенного примера?

Автор: _hunter 7.7.2004, 22:05
мда... не заметил sad.gif
а разве функция не должна вызываться так: Resume()?

Автор: Петрович 7.7.2004, 22:14
Нет, в Delphi (Pascal) при вызове процедуры (функции) без параметров указывать '()' не обязательно. Хотя, с ними нагляднее, и я последнее время стараюсь их писать.

Автор: Unregistered 8.7.2004, 09:17
Да, да hunter, внимательнее. smile.gif
Петрович, closehandle делаю. в свое время я уже сталкивался с проблемой незакрытых хендлов. А arrRequest динамический массив объявленный внутри класса TCommThread в секции Private.
В проге реализована возможность создавать и уничтожать потоки вручную (опрашивать/неопрашивать устройство). так я специально несколько раз останавливал и запускал - все нормально.

Автор: Петрович 8.7.2004, 13:35
Цитата
В проге реализована возможность создавать и уничтожать потоки вручную (опрашивать/неопрашивать устройство). так я специально несколько раз останавливал и запускал - все нормально.

В принципе, попробуй проверить программу на утечку памяти. Если ее нет, то даже и не заню что еще сказать sad.gif

Автор: Girder 8.7.2004, 13:40
Добавь FreeOnTerminate:=true, т.е:
Код
FreeOnTerminate:=true;
Resume;
end;
тогда при выходе из Execute(добавь на выходе arrRequest:=nil ну и т.п.) экземпляр класса автоматически освобождается.

Реализация Execute:
Код
procedure TCommThread.Execute;
begin
while not(Terminated) do
 begin
 ....
 end;
arrRequest:=nil;
....
end;
Тогда для удаления экземпляра:
Код
try
XXX.Terminate;
except
end;


Цитата
...программу на утечку памяти
Да похоже. У меня в одной проге от 1 до несколько тысяч запускается(и удаляются) потоков и ни когда таких проблемм не было.

Удачи.

Автор: Unregistered 9.7.2004, 07:21
Спасибо. Буду смотреть... если снова вылетит wink.gif

Автор: p0s0l 9.7.2004, 14:45
Попробуй выяснить что именно у тебя утекает (если утекает) - жми ctrl+alt+del, view->select columns и поставь галку handle count, может еще какие поставь - и смотри какие со временем будут быстро расти...
Если handle count растёт, то есть спец. проги (Process Explorer), там можно глянуть все открытые объекты в проге, а тут уж понятно станет что у тебя утекает...

И потом совет: лучше не убивай поток, а делай Suspend, а когда надо будет его пересоздать, делай Resume, но перед этим заново проделай инициализацию (то что в Create стоит) - так утечка хэндлов потоков уберется (а она есть, т.к. при уничтожении потока всё равно остается остаточная инфа (например, время уничтожения, время работы потока) до тех пор, пока не уничтожится процесс)... Не знаю, часто ли у тебя случаются сбои, и сколько в итоге за полгода накапливается этих мусорных потоков... Вполне возможно, что винда при нехватке ресурсов уничтожает этот мусор, но кто её знает...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)