|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
Доброго дня! Собственно, имеется программа (писал не я, только дорабатываю). В ней есть 4 потока (вообще их там больше, но для проведения эксперимента достаточно и их). Метод execute реализован следующим образом: procedure CL4Module.Execute; Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Содержимое FDEFINE Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
Содержимое FGET Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
Содержимое Destroy Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
Вызов уничтожения потока из тела основной программы: Код: pascal 1. 2. 3. 4. 5.
Процедуры FPUT и FGET служат для передачи событий между модулями. В FGET ожидание события сформировано на базе WaitForSingleObject. При вызове pL4Module.Terminate не происходит вообще ничего, pL4Module не обнуляется. При вызове FreeAndNil(pL4Module) вызывается Destroy. Если бы была открыта строка pL4Module.Suspend (как сейчас реализовано в проекте), то поток добросовестно убивается. Но это, насколько я понимаю, не верно. Если не вызывать Suspend, то программа попадает в destructor TThread.Destroy модуля classes, затем в WaitFor и начинает крутится в бесконечном цикле внутри TThread.WaitFor со значением WaitResult = 258. Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
И я в упор не представляю, что может быть не верно... Может кто подскажет, или хотя бы на мысль наведет? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2021, 15:49 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
BorodaOleg постоянно крутится в процедуре TThread.WaitFor Потому, что функция FGET висит - видимо, события ждёт, вечно. BorodaOleg Код: pascal 1. 2. 3.
В печь. Писателю - осиновый кол в сердце. BorodaOleg Вызов уничтожения потока из тела основной программы: Код: pascal 1. 2. 3. 4. 5.
В печь. Заменить на Код: pascal 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2021, 16:25 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
BorodaOleg При вызове pL4Module.Terminate не происходит вообще ничего BorodaOleg pL4Module не обнуляется. BorodaOleg Если бы была открыта строка pL4Module.Suspend (как сейчас реализовано в проекте), то поток добросовестно убивается BorodaOleg Код: pascal 1. 2. 3.
BorodaOleg Если не вызывать Suspend, то программа попадает в destructor TThread.Destroy модуля classes, затем в WaitFor и начинает крутится в бесконечном цикле внутри BorodaOleg Код: pascal 1.
Что нужно сделать: 1. Завести второй объект TerminateEvent и ждать в FGET двух хендлов. Если у вас все потоки останавливаются одновременно, то достаточно одного глобального события без автосброса. Если потоки останавливаются выборочно, то каждому потоку нужен свой объект 2. Написать адекватный деструктор потока Код: pascal 1. 2. 3. 4. 5. 6.
3. Весь код уничтожения потока сократить до одной строчки Код: pascal 1.
4. По завершению потока не забыть вызвать Код: pascal 1.
5. Строка Код: pascal 1.
лишняя ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2021, 16:28 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
BorodaOleg Если не вызывать Suspend, то программа попадает в destructor TThread.Destroy модуля classes, затем в WaitFor и начинает крутится в бесконечном цикле внутри BorodaOleg Код: pascal 1.
Что нужно сделать: 1. Завести второй объект TerminateEvent и ждать в FGET двух хендлов. Если у вас все потоки останавливаются одновременно, то достаточно одного глобального события без автосброса. Если потоки останавливаются выборочно, то каждому потоку нужен свой объект 2. Написать адекватный деструктор потока [src delphi] destructor CThread.Destroy; begin SetEvent(TerminateEvent) FreeAndNil(SenderClass); inherited Destroy; end; Было у меня подозрение, что проблема кроется именно в том, что поток крутится в WaitForSingleObject(pHiBuff[nIndex].w_mEvent, INFINITE), вот только не знаю как его оттуда вывести. Пытался кинуть в него сообщение (FPUT(BOX_L4,@m_nMsg)) но эффекта не дало. Вы предлагаете "Завести второй объект TerminateEvent и ждать в FGET двух хендлов", если честно, не совсем соображаю как. WaitForSingleObject, насколько я понимаю позволяет использовать только 1 event или я не прав? А если WaitForSingleObject зациклится на pHiBuff[nIndex].w_mEvent то как запустить ожидание 2-го handle? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2021, 17:09 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
BorodaOleg WaitForSingleObject, насколько я понимаю позволяет использовать только 1 event ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2021, 17:19 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
Кто мешает вместо INFINITE указать 100 и дальше ожидать в бесконечном цикле (колхоз конечно, но работать будет): Код: pascal 1. 2. 3. 4. 5. 6. 7.
В функцию FGET необходимо передавать объект потока, чтобы была возможность контролировать свойство Terminated. Пример такой передачи по ссылке (см. функцию ThreadWaitTimeout и доп. класс TThreadAccessTerminated). Это на случай, если функция FGET реализована в другом модуле. Либо сделать функцию FGET методом класса CThread ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2021, 17:28 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
Попытался сделать на WaitForMultipleObjects: Конструктор Create Код: pascal 1. 2. 3. 4. 5. 6.
Деструктор Destroy Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Функция FGETMULT Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27.
Описание массива в Type Код: pascal 1.
и в классе Код: pascal 1. 2.
Ну и собственно, сам вызов в Execute Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
и при закрытии программы Код: pascal 1. 2. 3.
В результате: 1. Намного дольше стала запускаться программа (раза в 2-3) 2. При закрытии программы долго скачет по WaitFor, в конце-концов выдает: 28.08.2021 14:19:59 : EThread: Thread Error: Неверный дескриптор (6) (0002CD80){knsmodule.exe} [0042DD80] utlbox.TThread.CheckThreadError (Line 9453, "utlbox" + 2) + $37 (0002CDC4){knsmodule.exe} [0042DDC4] utlbox.TThread.CheckThreadError (Line 9459, "utlbox" + 2) + $A (0002D0C5){knsmodule.exe} [0042E0C5] utlbox.TThread.WaitFor (Line 9722, "utlbox" + 17) + $16 (0002CCBB){knsmodule.exe} [0042DCBB] utlbox.TThread.Destroy (Line 9428, "utlbox" + 6) + $3 (0096945D){knsmodule.exe} [00D6A45D] utlbox.CThread.Destroy (Line 77, "utlThread.pas" + 14) + $9 (0090D872){knsmodule.exe} [00D0E872] utlbox.CL4Module.Destroy (Line 83, "knsl4module.pas" + 13) + $9 (0000341C){knsmodule.exe} [0040441C] utlbox.m_nSpeedList + $0 . . . Где я мог опять накосячить%( ... |
|||
:
Нравится:
Не нравится:
|
|||
28.08.2021, 14:24 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
О, безупречный WaitFor :-) взял попкорн :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
28.08.2021, 16:20 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
BorodaOleg Код: pascal 1.
Код: pascal 1.
Еще лучше Код: pascal 1.
но это уже не принципиально. Скорее защита от будущих потенциальных ошибок 2. Этот кусок BorodaOleg Код: pascal 1. 2. 3. 4. 5.
3. BorodaOleg и при закрытии программы Код: pascal 1. 2. 3.
_Vasilisk_ 3. Весь код уничтожения потока сократить до одной строчки Код: pascal 1.
4. BorodaOleg 2. При закрытии программы долго скачет по WaitFor, в конце-концов выдает: 28.08.2021 14:19:59 : EThread: Thread Error: Неверный дескриптор (6) ... |
|||
:
Нравится:
Не нравится:
|
|||
28.08.2021, 18:01 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
_Vasilisk_ BorodaOleg и при закрытии программы Код: pascal 1. 2. 3.
_Vasilisk_ 3. Весь код уничтожения потока сократить до одной строчки Код: pascal 1.
BorodaOleg Где я мог опять накосячить%( Много где. Раз ты такое пишешь, даже после советов ничего не делая - значит, ты не хочешь разбираться в том, что делаешь. А стоило бы, хотябы в азах. Зайди, для начала, в функции FreeAndNil, методы TObject.Free и TThread.Destroy и проштудируй их. В идеале ты в этом случае сможешь понять, почему не нужны лишние Terminate и проверки на Assigned. И еще 2 момента: 1. Ты создал именованный эвэнт. Это не нужно, поставь вместо имени nil (опять же, из-за нечтения документации и кода). Это не очень принципиально, но всё же. 2. Если ты в конструкторе класса что-то создаёшь - значит, надо убивать это в деструкторе, логика такая. Ты TerminateEvent создал, а убить забыл. Это лучше сделать после inherited Destroy (ведь пока он не выполнится - еще возможно его использование), и это касается всего. Т.е. примерно такой: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8.
... |
|||
:
Нравится:
Не нравится:
|
|||
28.08.2021, 18:51 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
YuRock Код: pascal 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
28.08.2021, 19:14 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
Спасибо всем кто подсказал/научил, все заработало! :) Осталось еще 18 потоков привести к общему знаменателю, и все Ок! :) ... |
|||
:
Нравится:
Не нравится:
|
|||
29.08.2021, 14:07 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
_Vasilisk_ . . . 4. BorodaOleg 2. При закрытии программы долго скачет по WaitFor, в конце-концов выдает: 28.08.2021 14:19:59 : EThread: Thread Error: Неверный дескриптор (6) Читал раньше: //Можно указать что после завершения кода поток завершится автоматически: MyThread.FreeOnTerminate:=true; А так как я потоки использовал без WaitFor, меня это устраивало. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.08.2021, 14:20 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
BorodaOlegЧитал раньше://Можно указать что после завершения кода поток завершится автоматически:MyThread.FreeOnTerminate:=true Никогда больше не посещайте ресурс где Вы прочли эту глупость. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
29.08.2021, 14:39 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
YuRock Много где. Раз ты такое пишешь, даже после советов ничего не делая - значит, ты не хочешь разбираться в том, что делаешь. А стоило бы, хотябы в азах. Зайди, для начала, в функции FreeAndNil, методы TObject.Free и TThread.Destroy и проштудируй их. В идеале ты в этом случае сможешь понять, почему не нужны лишние Terminate и проверки на Assigned. Код: pascal 1. 2. 3. 4. 5. 6. 7. 8.
Это, на случай, из исходников Delphi 7, файл SysUtils.pas. Я в курсе, что даже с nil FreeAndNil не ляснется, но вот я в этом проекте неоднократно встречался когда объект создается в классе A, передается в класс B, а оттуда в класс С, где его добросовестно убивают (не нужен стал, видать), а потом пытаются убить еще и в классе A. А чтобы "глупая ошибка" Access violation не выскакивала, они его в пустой try..except упаковывают. Как это можно отследить, я так и не смог допетрить. Лазил по всему тексту, отслеживал пустые исключения. YuRock И еще 2 момента: . . . 2. Если ты в конструкторе класса что-то создаёшь - значит, надо убивать это в деструкторе, логика такая. Ты TerminateEvent создал, а убить забыл. Это лучше сделать после inherited Destroy (ведь пока он не выполнится - еще возможно его использование), и это касается всего. Тут каюсь, забыл. Заколупался просто, 7-й день без выходных - мозги варить отказываются %( ... |
|||
:
Нравится:
Не нравится:
|
|||
29.08.2021, 14:52 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov BorodaOlegЧитал раньше://Можно указать что после завершения кода поток завершится автоматически:MyThread.FreeOnTerminate:=true Никогда больше не посещайте ресурс где Вы прочли эту глупость. https://thedelphi.ru/les/les54.php Не буду :) ... |
|||
:
Нравится:
Не нравится:
|
|||
29.08.2021, 14:53 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
BorodaOleg Я в курсе, что даже с nil FreeAndNil не ляснется BorodaOleg но вот я в этом проекте неоднократно встречался когда объект создается в классе A, передается в класс B, а оттуда в класс С, где его добросовестно убивают (не нужен стал, видать), а потом пытаются убить еще и в классе A. А чтобы "глупая ошибка" Access violation не выскакивала, они его в пустой try..except упаковывают. 1. Вы этом случае не поможет лишняя проверка на Assigned (разве что глобальная переменная). 2. Засовывать в try/except освобождение по мусорному адресу - это ужас, который рано или поздно аукнется, и ты получишь порчу памяти и полный крах. Надо исправлять логику проекта. Убирание говнокода помогает такому исправлению. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.08.2021, 19:58 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
BorodaOleg Жесть! Рекомендую этот материал для изучения многопоточного программирования. К сожалению, в нем не поднимается тема ожидания сразу нескольких событий. Но считаю, что там достаточно материала, чтобы можно было самостоятельно разобраться с WaitForMultipleObjects и MsgWaitForMultipleObjects. хотя автору это уже не нужно... ... |
|||
:
Нравится:
Не нравится:
|
|||
30.08.2021, 08:34 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
DmSer Жесть Виноват тот, кто придумал TThread. От него у новичков все беды. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.08.2021, 11:55 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
ъъъъъ DmSer Жесть Виноват тот, кто придумал TThread. От него у новичков все беды. Да вот как-то async/await не сразу изобрели. В последние 10 лет появляются то в одном, то в другом языке. А ведь именно это является панацеей от необходимости связываться с многопоточным программированием. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.08.2021, 13:37 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
Зачем было что-то изобретать если есть простой и понятный beginthread(ex)? Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
30.08.2021, 13:43 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov Зачем было что-то изобретать если есть простой и понятный beginthread(ex)? Покойный Архангельский про TThread писал. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.08.2021, 13:53 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov Зачем было что-то изобретать если есть простой и понятный beginthread(ex)? Доп. потоки в действительности нужны только для каких-то вычислений и обработки информации. Основные причины, когда мы их используем - это обмен по сети, обмен с устройством, запросы к базе данных, работа с файлами. Благодаря async / await обмен по сети, обмен с устройством, запросы к БД, работа с файлами перебираются в главный поток и не парят программисту мозги многопоточностью. Колоссальный выигрыш получают сервера (например TCP или HTTP-сервер), т.к. с многопоточностью не связываешься, а код получается быстрый, простой и понятный. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.08.2021, 14:28 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
DmSer Да вот как-то async/await не сразу изобрели. В последние 10 лет появляются то в одном, то в другом языке. А ведь именно это является панацеей от необходимости связываться с многопоточным программированием. но в целом что дельфи с TThread, что шарп c Async собрали все грабли с контекстом ... |
|||
:
Нравится:
Не нравится:
|
|||
30.08.2021, 14:28 |
|
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
|
|||
---|---|---|---|
#18+
kealon(Ruslan) DmSer Да вот как-то async/await не сразу изобрели. В последние 10 лет появляются то в одном, то в другом языке. А ведь именно это является панацеей от необходимости связываться с многопоточным программированием. но в целом что дельфи с TThread, что шарп c Async собрали все грабли с контекстом об чём речь? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.08.2021, 14:31 |
|
|
start [/forum/topic.php?fid=58&msg=40093625&tid=2037070]: |
0ms |
get settings: |
8ms |
get forum list: |
16ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
40ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
53ms |
get tp. blocked users: |
1ms |
others: | 296ms |
total: | 433ms |
0 / 0 |