| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Thread creation error |
| Автор: Unregistered 6.7.2004, 01:53 |
| Программа в отдельном потоке опрашивает устройство через ком-порт. Опрос идет непрерывно, круглосуточно. Если в обмене происходит какой-то сбой, то поток убивается и создается по новой. Отработала прога уже больше полугода и вот какая проблема случилась: в одно прекрасное утро обмен прекратился. Прога выдала ошибку "Thread creation error. Подсоединенное к системе устройство не работает". После перезагрузки системы все опять заработало. В проге не стоит проверка на корректность создания потока, отсюда и ошибка вылетает-это понятно. Непонятны причины по которым система не может создать поток. Может кто-нибудь объяснить? Спасибо. |
| Автор: <Spawn> 6.7.2004, 08:03 | ||
для этого желательно бы код посмотреть его содзадия или самому написать обработчик ошибок примерно следующего содержания:
Если это была системная ошибка, а не генерируемая Дельфийским наследником Exception. |
| Автор: Петрович 6.7.2004, 11:49 |
| А какая система? Слышал (сам не проверял), что Win9x при создании+уничтожении потока безвозвратно теряет часть системных ресурсов. Причем, в источнике информации было даже сказанно сколько и каких, но к сожалению, не помню где он этот источник. Если это так, то при очень длительной работе системы без перезагрузки, если какой-либо из процессов периодически создает и удаляет потоки, то однажды это ему не удасться У тебя очень похоже на это. |
| Автор: _hunter 6.7.2004, 16:14 |
| насколько я слышал |
| Автор: 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 | ||||||
Может остальные в этот момент просто не пыталсь пересоздать поток?
А при уничтожении потока (в 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 | ||
Как это не увидел? А как ты думаешь, что делает Resume в конце приведенного примера? |
| Автор: _hunter 7.7.2004, 22:05 |
| мда... не заметил а разве функция не должна вызываться так: Resume()? |
| Автор: Петрович 7.7.2004, 22:14 |
| Нет, в Delphi (Pascal) при вызове процедуры (функции) без параметров указывать '()' не обязательно. Хотя, с ними нагляднее, и я последнее время стараюсь их писать. |
| Автор: Unregistered 8.7.2004, 09:17 |
| Да, да hunter, внимательнее. Петрович, closehandle делаю. в свое время я уже сталкивался с проблемой незакрытых хендлов. А arrRequest динамический массив объявленный внутри класса TCommThread в секции Private. В проге реализована возможность создавать и уничтожать потоки вручную (опрашивать/неопрашивать устройство). так я специально несколько раз останавливал и запускал - все нормально. |
| Автор: Петрович 8.7.2004, 13:35 | ||
В принципе, попробуй проверить программу на утечку памяти. Если ее нет, то даже и не заню что еще сказать |
| Автор: Girder 8.7.2004, 13:40 | ||||||||
Добавь FreeOnTerminate:=true, т.е:
Реализация Execute:
Удачи. |
| Автор: Unregistered 9.7.2004, 07:21 |
| Спасибо. Буду смотреть... если снова вылетит |
| Автор: p0s0l 9.7.2004, 14:45 |
| Попробуй выяснить что именно у тебя утекает (если утекает) - жми ctrl+alt+del, view->select columns и поставь галку handle count, может еще какие поставь - и смотри какие со временем будут быстро расти... Если handle count растёт, то есть спец. проги (Process Explorer), там можно глянуть все открытые объекты в проге, а тут уж понятно станет что у тебя утекает... И потом совет: лучше не убивай поток, а делай Suspend, а когда надо будет его пересоздать, делай Resume, но перед этим заново проделай инициализацию (то что в Create стоит) - так утечка хэндлов потоков уберется (а она есть, т.к. при уничтожении потока всё равно остается остаточная инфа (например, время уничтожения, время работы потока) до тех пор, пока не уничтожится процесс)... Не знаю, часто ли у тебя случаются сбои, и сколько в итоге за полгода накапливается этих мусорных потоков... Вполне возможно, что винда при нехватке ресурсов уничтожает этот мусор, но кто её знает... |