|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
@GunSmoker авторТы до сих пор свой .Execute так и не показал - а это ведь самое важное в вопросе, а вовсе не как ты создаёшь или завершаешь поток. каюсь и исправляюсь. автор- При смене фильтра: если есть старый поток - делай ему .Terminate, но не жди его, сразу запускай новый - Если надо остановить поток - делай ему .Terminate и забывай ссылку - В самом потоке проверяй .Terminated в .Execute - При выходе из потока - вызывай OnTerminate для того места, где у тебя ссылка на поток. Если ссылка = ты, то скидывай результаты на UI, если ссылка = не ты, то просто удаляй результаты. В конце удали себя так и делал. Назначил обработчик на OnTerminate. в нем сделал Free для объекта. В Execute добавил в конце цикла фетчинга Terminate. Вся цепочка отрабатывет прекрасно - датасет и база закрываются и разрушаются, ссылка освобождается и аозволяет создать и запустить новую нить, но переходит в inherited Destroy и останавливается на WaitFor. Mелкий нюанс с WaitFor портит всю работу-выполнение кода висит там ну очень долго, я даже не знаю сколько. Естественно FASTMM рапортует о потеряной памяти как раз из этой нити. Но при ручном логировании записывается подтверждение, что объект разрушен и память свободна - видимо нестыковка по времени завершения нити и процесса. -------------------------------------- Множественные копии нити дают тормоза. Поэтому решил перейти к совету коллеги @Fr0sT-Brutal - нить не убивать, но каждый раз менять ей SQL Код: 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. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68.
При запуске стартует нормально. Сделал ограничение в запросе на показ только 3х записей за раз. При скроллинге ListBox идет запрос следующих трех и т.д. Это идея. В реальности саспендед нить разбудить не получается. В доке нашел такую фигню: авторWarning: Suspend is deprecated. Pauses a running thread. Suspend was intended to be used by debuggers and is deprecated in RAD Studio XE, in the year 2010. Call Suspend to temporarily halt the execution of the thread. To resume execution after a call to Suspend, call Resume. Calls to Suspend can be nested; Resume must be called the same number of times Suspend was called before the thread resumes execution. Warning: The Resume and Suspend methods should only be used for debugging purposes. Suspending a thread using Suspend can lead to deadlocks and undefined behavior within your application. Proper thread synchronization techniques should be based on TEvent and TMutex. ... и по resume поток более не просыпается. Как тогда "усыплять" нить? ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 12:34 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
два раза запостил.. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 12:35 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
svdКак тогда "усыплять" нить? TQueue.Wait. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 12:58 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov, авторTQueue.Wait. нигде не нашел такого класса. Это что то нестандартное? Можно пример как с этим работать? ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 13:08 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
svd Dimitry Sibiryakov, авторTQueue.Wait. нигде не нашел такого класса. Это что то нестандартное? Можно пример как с этим работать? Не слушай ты его :) Зачем? Просто делай sleep(10) или sleep(100) в конце цикла? Тебе же условие Terminated нужно же проверять периодически! PS: не увидел WaitFor(). Не понял зачем он нужен, ведь потока уже к этому наверняка прибит. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 13:12 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
svdнигде не нашел такого класса. Странно, вроде бы в свежих дельфях была очередь с ожиданием... Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 13:24 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov Странно, вроде бы в свежих дельфях была очередь с ожиданием... Код: pascal 1. 2. 3.
... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 13:41 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
Belotsky Serge, авторне увидел WaitFor(). Не понял зачем он нужен, ведь потока уже к этому наверняка прибит. System.Classes: Код: 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. 28. 29. 30. 31.
Сторока 13 в коде. Он нужен, чтоб освободить доступ к какому то объекту. И он дествует до бесконечности, пока этот лок не снимет счетчик. Где он делает захват - не представляю. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 14:15 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
svd Belotsky Serge, авторне увидел WaitFor(). Не понял зачем он нужен, ведь потока уже к этому наверняка прибит. System.Classes: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.
Сторока 13 в коде. Он нужен, чтоб освободить доступ к какому то объекту. И он дествует до бесконечности, пока этот лок не снимет счетчик. Где он делает захват - не представляю. Как-то все сложно для меня. Обычно WaitFor вызывается из основного потока, что-то типа: Код: pascal 1. 2. 3. 4. 5.
Но если у вас есть обработчик OnTerminate, то зачем WaitFor? ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 14:36 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
Belotsky Serge, если смотреть внимательно - то это не мой класс, а класс "из коробки". Я могу его изменить у себя, у коллег он не изменится. Да и не правильно это делать. И игнорировать его тоже нельзя - Destroy должен всю цепочку вложений выполнить. Если войти в WaitFor, то там он вызывает WaitForSingeObject на этот хэндл с параметром ждать до бесконечности. То есть хэндл гдето застрял. Подозреваю в каких то списках. Могу к этому еще добавить, что иногда программа при завершении делает долгую финализацию. При ислледовании оказалось, что другая нить при определенных обстоятельствах тоже долго не завершается, но по протоколу вроде как "умирает" с освобождением ресурсов. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 14:44 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
svdЯ могу его изменить у себя Зато у себя ты можешь его правильно использовать, не загоняя в deadlock. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 14:52 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
svd Belotsky Serge, если смотреть внимательно - то это не мой класс, а класс "из коробки". Я могу его изменить у себя, у коллег он не изменится. Да и не правильно это делать. И игнорировать его тоже нельзя - Destroy должен всю цепочку вложений выполнить. Если войти в WaitFor, то там он вызывает WaitForSingeObject на этот хэндл с параметром ждать до бесконечности. То есть хэндл гдето застрял. Подозреваю в каких то списках. Могу к этому еще добавить, что иногда программа при завершении делает долгую финализацию. При ислледовании оказалось, что другая нить при определенных обстоятельствах тоже долго не завершается, но по протоколу вроде как "умирает" с освобождением ресурсов. Ну и будете ждать до потери пульса :) Вы откуда вызываете Free потока из OnTerminate? Так OnTerminate вызывается по выходу из Execute потока. После того как вызвали Free потока вызывается Destroy, в котором вы говорите ему завершить Execute (Terminate) и потом ждете пока он завершится. Но поток уже вышел из Excecute и обратно уже никогда не вернется :) ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 15:35 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
Belotsky Serge, не, эта схема не живая. Сделал трэд все время живой. только по окончании фетча отключается датасет и ждет прихода нового запроса. Вроде работает, неплохо. Сейчас возникла идея использовать всего единственный фетч для показа во всех фреймах. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 15:56 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
Мнение сугубо личное, но проверенное практикой. Дельфийская оболочка с объектами вокруг CreateThread скорее мешает, чем помогает. Точнее, не помогает вообще никак. Пишется чистая процедура потока, запускается через CreateThread, все управление - через объекты синхронизации. Если задача потока разовая - запустил и забыл. Если задача циклическая - в конце цикла поток ждет сигнал либо на новый цикл (или не ждет - ваша логика), либо на выход. Приложению в таком случае не забыть перед закрытием дать сигнал на выход. Все. А Delphi к этому простому делу пристраивает объекты, с которыми теперь надо репу чесать - кто, когда и как их должен освобождать? ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 16:16 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
shalamyansky Мнение сугубо личное, но проверенное практикой. Дельфийская оболочка с объектами вокруг CreateThread скорее мешает, чем помогает. Точнее, не помогает вообще никак. Пишется чистая процедура потока, запускается через CreateThread, все управление - через объекты синхронизации. Если задача потока разовая - запустил и забыл. Если задача циклическая - в конце цикла поток ждет сигнал либо на новый цикл (или не ждет - ваша логика), либо на выход. Приложению в таком случае не забыть перед закрытием дать сигнал на выход. Все. А Delphi к этому простому делу пристраивает объекты, с которыми теперь надо репу чесать - кто, когда и как их должен освобождать? Имхо, всё же проще ч/з System.BeginThread(). 22423366 ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 16:27 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
svd так и делал. Назначил обработчик на OnTerminate. в нем сделал Free для объекта. Останавливать поток удобно с помощью функций WaitForSingleObject/WaitForMultipleObjects или при помощи класса TEvent и его методов WaitFor, SetEvent, ResetEvent. Например в коде потока, если нужно, чтобы поток что-то сделал и снова приостановился. Код: pascal 1. 2. 3. 4. 5. 6. 7. 8.
Из главной формы: чтобы разбудить и поток сделал что-то: Код: pascal 1.
чтобы прекратить выполнение потока Код: pascal 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 16:41 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
svd Назначил обработчик на OnTerminate. в нем сделал Free для объекта. svd В Execute добавил в конце цикла фетчинга Terminate. svd Вся цепочка отрабатывет прекрасно Разбил на отдельные цитаты для удобства, наглядности. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 17:13 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
svd Если войти в WaitFor, то там он вызывает WaitForSingeObject на этот хэндл с параметром ждать до бесконечности. То есть хэндл гдето застрял. Подозреваю в каких то списках. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 17:17 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
ъъъъъ shalamyansky Мнение сугубо личное, но проверенное практикой. Дельфийская оболочка с объектами вокруг CreateThread скорее мешает, чем помогает. Точнее, не помогает вообще никак. Пишется чистая процедура потока, запускается через CreateThread, все управление - через объекты синхронизации. Если задача потока разовая - запустил и забыл. Если задача циклическая - в конце цикла поток ждет сигнал либо на новый цикл (или не ждет - ваша логика), либо на выход. Приложению в таком случае не забыть перед закрытием дать сигнал на выход. Все. А Delphi к этому простому делу пристраивает объекты, с которыми теперь надо репу чесать - кто, когда и как их должен освобождать? Имхо, всё же проще ч/з System.BeginThread(). 22423366 ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 17:20 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
YuRock, кроме "той" переменной, посмотри, как функция треда в CreateThread() передается. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 17:32 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
YuRockмногопоточный доступ к памяти может возникнуть до первого запуска BeginThread, извне. Из какого "вне" если у него приложение, а не библиотека? Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 18:34 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov YuRockмногопоточный доступ к памяти может возникнуть до первого запуска BeginThread, извне. Из какого "вне" если у него приложение, а не библиотека? Ага, я как-то не установил IsMultiThread, было смешно. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 18:54 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
ъъъъъ YuRock, кроме "той" переменной, посмотри, как функция треда в CreateThread() передается. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 19:31 |
|
Как правильно убивать thread
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov YuRockмногопоточный доступ к памяти может возникнуть до первого запуска BeginThread, извне. Из какого "вне" если у него приложение, а не библиотека?Я про то, что BeginThread вместо CreateThread - это не панацея в общем случае от неинициализированной переменной IsMultiThreaded. И "в приложении, а не в библиотеке" тоже никто не запрещает инициализировать её после begin в dpr и затем использовать CreateThread. Как минимум это быстрее на один вызов функции. Для меня до сих пор загадка, для чего BeginThread вообще ввели. Написали бы в хелпе обязательно инициализировать IsMultiThreaded, да и всё. Тем более, что не редко приходится это делать даже в библиотеках, не стартующих потоки вообще. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 19:35 |
|
|
start [/forum/topic.php?fid=58&msg=40128171&tid=2036694]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
52ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
56ms |
get tp. blocked users: |
2ms |
others: | 15ms |
total: | 168ms |
0 / 0 |