|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Работаю над учебником "Многопоточное программирование в Delphi для начинающих". Учебник вместе с примерами доступен по ссылке: https://github.com/loginov-dmitry/multithread Примеры должны компилироваться во всех версиях Delphi, начиная с Delphi 2007 (кроме примера Ex12, где рассматривается метод Queue). В настоящее время в учебнике 58 страниц. Описаны минимальные базовые вещи, которые позволят начинающему разобраться с многопоточностью и начать разработку реальных проектов. Прошу отнестись к данной работе критически, т.к. есть желание (цель) давать ссылки на данный учебник при возникновении вопросов по многопоточности. Я потратил на эту работу в сумме около месяца и будет обидно читать комментарии типа "на второй странице пропущена запятая, значит всё там неправильно и читать дальше не буду". К сожалению, я успел описать далеко не всё, что хотелось бы. Надеюсь, что мне удастся и дальше продолжить эту работу (не в ущерб основной работе). В настоящее время оглавление следующее: Оглавление1. Вступление 1.1 Для чего используется многопоточное программирование в Delphi 1.2 В чём сложность разработки многопоточных программ в Delphi по сравнению с другими современными языками программирования 1.3 Поддержка многопоточности в операционных системах и процессорах 2. Базовый класс многопоточности - TThread 3. Предотвращаем зависание основного потока (имитация задачи длительного вычисления) 4. Управление временем жизни потоков 4.1 Использование свойства TThread.Terminated для выхода из метода Execute 4.2 Главная форма отвечает за прекращение работы потока и уничтожение объекта потока 4.3 Главная форма отвечает за уничтожение объекта потока с разовой задачей 17стр. 4.4 Главная форма отвечает за уничтожение нескольких долгоживущих потоков 19 4.5 Использование списка TObjectList для хранения ссылок на объекты потоков 23 4.6 Простой пример организации паузы в работе потока 26 4.7 Использование свойства FreeOnTerminate для автоматического уничтожения объекта потока при завершении работы потока 27 4.8 Организация корректного завершения работы программы при использовании свойства FreeOnTerminate 28 5. Передача информации из дополнительного потока в основной 32 5.1 Обращение к визуальным компонентам формы из дополнительного потока – как нельзя делать 32 5.2 Использование метода TThread.Synchronize для передачи данных в основной поток 32 5.3 Периодическое чтение основным потоком данных, подготовленных в дополнительном потоке 36 5.4 Использование функции SendMessage для передачи данных в основной поток 40 5.5 Использование функции PostMessage для передачи очереди сообщений в основной поток 44 5.6 Использование списка TThreadList для передачи очереди данных в основной поток 46 5.7 Использование метода TThread.Synchronize для передачи данных в основной поток – вариант с использованием анонимной процедуры 50 5.8 Использование метода TThread.Queue для передачи данных в основной поток 51 6. Где можно и где нельзя создавать и уничтожать потоки 57 ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 12:09 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer, привет, начал читать. Что касается "запятых" ("а второй странице пропущена запятая...") то по-моему как раз язык нормальный, мысли пока что, сколько прочитал, были по-моему выражены ясно. ) Дочитал до начала описания класса TThread. Мне показалось, что есть "дырка" в изложении - переход от общего описания многопоточности в ОС к классу TThread. Может быть стоит написать про функцию CreateThread, при помощи которой можно создать поток в вызывающем её процессе (более строго, по документации: "который выполняется в адресном пространстве вызывающего процесса") и которую TThread инкапсулирует? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 13:24 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
s62 DmSer, привет, начал читать. Что касается "запятых" ("а второй странице пропущена запятая...") то по-моему как раз язык нормальный, мысли пока что, сколько прочитал, были по-моему выражены ясно. ) Дочитал до начала описания класса TThread. Мне показалось, что есть "дырка" в изложении - переход от общего описания многопоточности в ОС к классу TThread. Может быть стоит написать про функцию CreateThread, при помощи которой можно создать поток в вызывающем её процессе (более строго, по документации: "который выполняется в адресном пространстве вызывающего процесса") и которую TThread инкапсулирует? Спасибо за предложение! Но мне кажется, это будет лишняя информация для начинающих. Очень сложно разобраться, какой материал нужно включать, какой не нужно. Тонкостей различных миллион! Если описывать про CreateThread, а это чисто виндовая функция, тогда придётся описывать аналоги и в других ОС (Linux, MacOS, Android). Вероятно, можно будет обойтись более общей формулировкой о том, что доп. поток на самом деле создаёт ОС, а класс TThread является обёрткой... ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 14:03 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSerЕсли описывать про CreateThread, а это чисто виндовая функция Причём такая, которой не надо пользоваться практически никогда. _beginthreadex() описать таки надо. Хотя бы пробы было понимание, что "TThread это не поток". Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 14:17 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Вероятно, можно будет обойтись более общей формулировкой о том, что доп. поток на самом деле создаёт ОС, а класс TThread является обёрткой... ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 15:41 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Работаю над учебником "Многопоточное программирование в Delphi для начинающих". так вот почему такой странный топик про потоки. А я-то воспринял, как будто новичок украл твой ник и забавляется. Извини за наезд :) Исходник книги на чем пишешь? Я тут кое-что время от времени перевожу, из markdown экспортируется весьма читабельно, а у тебя бледненько - текст труднее воспринимается ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 16:24 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer> Работаю над учебником "Многопоточное программирование в Delphi для начинающих". Это дело хорошее, полезное. Научный редактор есть или ты надеешься на краудсорсинговую вычитку? > Примеры должны компилироваться во всех версиях Delphi, начиная > с Delphi 2007 (кроме примера Ex12, где рассматривается метод Queue). В Д7 не проверялось? Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 16:56 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Чтобы разрабатывать реальные проекты надо не многопоточность изучать, а терминологию и практики... Очень хороший пример всего этого описан в ответе здесь . Далее.. Delphi сейчас - это кроссплатформенная среда разработки, следовательно все примеры должны быть кроссплатформенные. Все что в современной версии досталось в наследство от 1-7 версий должно быть похоронено как deprecated. У этого всего давно появились другие аналоги, более удобные в проектировании и разработке. Как минимум уже в начале неверно описана область применения PPL. PPL - это способ выполнить некую работу (не важно какую, абсолютно любую) конкурентно не вдаваясь в детали реализации. Как она будет выполнена: параллельно, асинхронно или синхронно - это дело десятое и в современно мире особо об этом задумываться ненужно. Когда над проектом работают десятки разработчиков, порог входа должен быть низкий, чтобы иметь возможность дешево менять ресурсы, для этого и придумывают различные библиотеки и абстракции, которые в освоении намного проще. Проблема в Дельфи в том, что разработчики которые туда пытаются придти учатся по книжкам которые написаны были во времена высокого порога входа в программирование, а не когда курсы клепают по 100 "программистов" в день... Поэтому лучше, чтобы появлялись книжки, которые позволят вчерашним студентам, которые не знают как там работает под капотом, да и не надо им знать, но которые будут эффективно решать реальные бизнес-задачи используя современные инструменты. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 17:04 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
авторЯ хотел бы выделить две основные причины использования многопоточности в Delphi-программах Задачи длительного ожидания завершения ввода-вывода. Вы путаете теплое с мягким. Такие задачи должны выполняться асинхронно.. Другой поток - это способ реализации, при чем довольно не эффективный, если таких запросов много. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 17:24 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Первый пример показан через оверхед. Намного лаконичнее решается через Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9.
И кстати, такая вариация намного удачнее, чем через отдельный класс, потому что явно видно в каком месте какую работу необходимо выполнить в потоке отличном от вызываемого. А еще лучше так никогда не делать и не показывать что вообще можно... Потому что Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9.
намного лучше, т.к. нет оверхеда на создание/разрушение потоков Лучше учить решать задачи наиболее подходящим инструментом, чем учить использовать примитив везде где попало. Иначе книжку надо переименовать в Работа с классом TThread, а не многопоточное программирование... ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 18:15 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite лучше, чтобы появлялись книжки, которые позволят вчерашним студентам, которые не знают как там работает под капотом, да и не надо им знать, но которые будут эффективно решать реальные бизнес-задачи используя современные инструменты. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 18:23 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite Код: pascal 1.
Что будет, если DoLongCalculations будет выполняться часами, а пользователь захочет закрыть программу? Нежданчик? И таким "современным" методам вы предлагаете учить молодежь? Чтобы они и не знали, как сделать по-нормальному, чтобы контролировать всё? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 18:29 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
YuRock, Почти все проблемы для известных и популярных библиотек уже описаны и описаны способы решения. В том числе например и для PPL. Проще обучить как решать задачи для которых PPL предпочтительнее, чем решать эти же задачи на TThread ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 18:30 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite YuRock, Почти все проблемы для известных и популярных библиотек уже описаны и описаны способы решения. В том числе например и для PPL. Проще обучить как решать задачи для которых PPL предпочтительнее, чем решать эти же задачи на TThread Какие нафиг библиотеки, я не про них говорю, а про реальные проекты, которые будут делать программисты. Научить TTask'у, конечно, проще, чем TThread'у, только толку от этого ученика не будет. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 18:34 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
YuRock X-Cite Код: pascal 1.
Что будет, если DoLongCalculations будет выполняться часами, а пользователь захочет закрыть программу? Нежданчик? жданчик будет. Ошибки, зависания, прочие прелести. Я от TTask отказался как раз из-за абсолютно фантастических вещей при его остановке. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 18:39 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
YuRock Что будет, если DoLongCalculations будет выполняться часами, а пользователь захочет закрыть программу? Тоже самое что и в TThread.Execute(), но в отличие от TThread бизнес-единица алгоритма будет всегда в согласованном состоянии. Примеры: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Что будет? Access Violation будет. Отстрелили ногу. TTask.Run - корректно дождется конца. т.е. в TThread как минимум надо самостоятельно ждать окончания работы, чтобы корректно продолжить. Что надо сделать чтобы не ждать конца? А закончить работу пораньше. Одно и тоже, что в TTask что в TThread - только способы реализации будут разные. Только с CreateAnonymousThread - все намного сложнее, окей, применяем старый подход через отдельный класс Реализация для TThread Код: 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.
Реализация для TTask Код: 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.
И что мы видим... Работает и то и то. Но преимущества TTask 1) Код не размазан и лаконичен 2) Нет оверхеда на создание/уничтожение потоков 3) Задачу выполнения работы решает не примитив (поток), а инструмент (задача) который по факту может ее решить как угодно, вплоть до делегирования другому процессу. Вы как поставите задачу подчиненному программисту? 1) Произвести запись в файл асинхронно. 2) Произвести запись в файл используя отдельный поток. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 19:54 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite Что будет? Access Violation будет. С чего бы? GUI-поток завершится, но это не беда. Процесс будет жить, пока другой поток (другие потоки) не закончит свою работу. Вторичному потоку, который пишет в файл, от бывшего главного вроде бы ничего не нужно. Допишет файл, и тихо выйдет. По идее. На практике не проверил. Единственно, что вызывает сомнения - не будет ли сломан менеджер памяти, который должен на выходе из процедуры освободить байтовый массив. На первый взгляд, не будет. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 20:42 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док так вот почему такой странный топик про потоки. А я-то воспринял, как будто новичок украл твой ник и забавляется. Извини за наезд :) Все нормально! У меня в тот момент возникли сложности с тем, как лучше описать Queue. Не получалось её описать в позитивном ключе. А тему завел по причине того, что у некоторых разработчиков на этом форуме есть положительный опыт и позитивные отзывы. В результате та тема мне очень помогла, удалось очень подробно описать Queue в позитивном ключе. А кое-кто писал, что на оф. сайте по Queue всё есть, головой только немного подумать нужно. Ну да, я подумал, разобрался (вроде), но страшно представить, сколько времени уйдет у новичка, если он будет методом тыка все грабли перебирать. Док Исходник книги на чем пишешь? Я тут кое-что время от времени перевожу, из markdown экспортируется весьма читабельно, а у тебя бледненько - текст труднее воспринимается Пишу в ворде 2010года. Про markdown не знал, спасибо. Почитаю, пока отпуск! В идеале хотелось бы пользоваться специализированным решением, которое было бы совместимо с системой контроля версий. Но при этом не тратить много времени. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 22:31 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Гаджимурадов Рустам DmSer> Работаю над учебником "Многопоточное программирование в Delphi для начинающих". Это дело хорошее, полезное. Научный редактор есть или ты надеешься на краудсорсинговую вычитку? Я надеюсь, что если там есть откровенная лажа, то она без внимания не останется :) При этом понимаю, что читать 58 страниц такого текста - это не роман прочитать. За час не управишься! :) Гаджимурадов Рустам > Примеры должны компилироваться во всех версиях Delphi, начиная > с Delphi 2007 (кроме примера Ex12, где рассматривается метод Queue). В Д7 не проверялось? Я использую модуль TimeIntervals, там есть класс TTimeInterval, который является рекордом с методами. В D7 такое не скомпилится. Также я предполагаю, что в D7 были бы проблемы с отображением исходников в кодировке UTF-8. А мне приходится использовать UTF-8 для корректного отображения в гитхабе. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 22:40 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite Чтобы разрабатывать реальные проекты надо не многопоточность изучать, а терминологию и практики... Очень хороший пример всего этого описан в ответе здесь . Далее.. Delphi сейчас - это кроссплатформенная среда разработки, следовательно все примеры должны быть кроссплатформенные. Все что в современной версии досталось в наследство от 1-7 версий должно быть похоронено как deprecated. У этого всего давно появились другие аналоги, более удобные в проектировании и разработке. Как минимум уже в начале неверно описана область применения PPL. PPL - это способ выполнить некую работу (не важно какую, абсолютно любую) конкурентно не вдаваясь в детали реализации. Как она будет выполнена: параллельно, асинхронно или синхронно - это дело десятое и в современно мире особо об этом задумываться ненужно. Когда над проектом работают десятки разработчиков, порог входа должен быть низкий, чтобы иметь возможность дешево менять ресурсы, для этого и придумывают различные библиотеки и абстракции, которые в освоении намного проще. Проблема в Дельфи в том, что разработчики которые туда пытаются придти учатся по книжкам которые написаны были во времена высокого порога входа в программирование, а не когда курсы клепают по 100 "программистов" в день... Поэтому лучше, чтобы появлялись книжки, которые позволят вчерашним студентам, которые не знают как там работает под капотом, да и не надо им знать, но которые будут эффективно решать реальные бизнес-задачи используя современные инструменты. Я достаточно много думал о том, нужно ли описывать базовые вещи, или сразу начать с PPL. Моя уверенность в том, что важнее описать базовые вещи укрепилась после серии вопросов на этом форуме, которые относятся к PPL, а также к CreateAnonymousThread от начинающих программистов и не очень. Да, начинающего программиста можно, как мартышку, научить выполнять конкретное действие через TTask.Run. Но он нихрена не понимает, как это работает, если не знает базовые вещи. Проблема в Дельфи в том, что там нет того асинхронного программирования, которое есть в C#, JavaScript, Rust, Kotlin и некоторых других ЯП. В ЯП, где есть асинхронная конструкция async/await (либо аналоги), программисты решают реальные бизнес-задачи и как раз там им не требуется задумываться о том, как задача будет выполнена: параллельно, асинхронно или синхронно. В языках, которые изначально спроектированы как многопоточные (имею ввиду прежде всего GoLang) в сто раз меньше связанных с многопоточностью проблем и граблей, чем в языке Delphi. А теперь им еще и шедулер улучшили! ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 22:58 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite авторЯ хотел бы выделить две основные причины использования многопоточности в Delphi-программах Задачи длительного ожидания завершения ввода-вывода. Вы путаете теплое с мягким. Такие задачи должны выполняться асинхронно.. Другой поток - это способ реализации, при чем довольно не эффективный, если таких запросов много. Да, должны! Но какого объёма книжку нужно написать для начинающего, чтобы он смог написать красивую, надёжную, быструю программу с использованием, скажем Overbyte ICS? А будет ли он читать такую книгу? А что ему даст асинхронность Overbyte ICS (какое преимущество), если ему потребовалось запрос к БД выполнить? А будет ли он читать такую книгу, если тут на форуме все примеры в основном на Indy? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 23:04 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite Потому что Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9.
намного лучше, т.к. нет оверхеда на создание/разрушение потоков Лучше учить решать задачи наиболее подходящим инструментом, чем учить использовать примитив везде где попало. Иначе книжку надо переименовать в Работа с классом TThread, а не многопоточное программирование... В интернете достаточно хороших примеров того, как использовать PPL. Мне и добавить к ним нечего. Пусть начинающие учатся по этим примерам, ради Бога! Если удастся работать эффективно, я буду только рад за них. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 23:09 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Хорошо работающая PPL это благо для начинающих (и не только). Либо заголовок не правильный, либо план учебника ... ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 23:26 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite Код: 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.
. И тут блестящая PPL разом превратилась в тыкву! Оказывается, как и с TThread, нужно останавливать таски перед завершением программы, а в таске проверять необходимость завершения :) ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 23:27 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Оказывается ... Так ты знаешь PPL или только TThread ? :) ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 23:32 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Dmitry Arefiev Хорошо работающая PPL это благо для начинающих (и не только). Либо заголовок не правильный, либо план учебника ... Возможно в будущем появятся разделы, посвящённые PPL. Тем более PPL все активнее вторгается в нашу жизнь :) Но и помимо PPL есть много тем, которые хотелось бы описать (например, руки пока не дошли до описания темы синхронизации между потоками, а это, я считаю, очень важно). Но благодаря реализации функции ThreadWaitTimeout удаётся до последнего оттягивать такую сложную для понимания тему, как эвенты. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 23:34 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Dmitry Arefiev DmSer Оказывается ... Так ты знаешь PPL или только TThread ? :) Я изучал довольно много материала по PPL, смотрел видео-уроки, проводил некоторые эксперименты, так что считаю, что знаю о ней достаточно много. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2020, 23:37 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer X-Cite Код: 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.
. И тут блестящая PPL разом превратилась в тыкву! Оказывается, как и с TThread, нужно останавливать таски перед завершением программы, а в таске проверять необходимость завершения :) Это еще не идёт речь о том, что часто потоки нужно завершать в определенном порядке. Как это сделать с тасками - объяснить начинающему программисту будет проблематично :) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.07.2020, 00:32 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer (имею ввиду прежде всего GoLang) в сто раз меньше связанных с многопоточностью проблем и граблей, чем в языке Delphi. А теперь им еще и шедулер улучшили! ты про шедулершедулер или gc? ... |
|||
:
Нравится:
Не нравится:
|
|||
09.07.2020, 06:17 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Дегтярев Евгений DmSer (имею ввиду прежде всего GoLang) в сто раз меньше связанных с многопоточностью проблем и граблей, чем в языке Delphi. А теперь им еще и шедулер улучшили! ты про шедулершедулер или gc? Раньше кооперативный планировщик был, а работу планировщика ОС они грубо говоря игнорировали. Теперь учитывают. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.07.2020, 08:50 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
YuRock Это еще не идёт речь о том, что часто потоки нужно завершать в определенном порядке. Как это сделать с тасками - объяснить начинающему программисту будет проблематично :) Опять путаница между теплым и мягким. Есть различные задачи, которые надо реализовать. Эти все задачи можно и нужно отнести к определенным классам задач. И здесь вступает в игру то, что для разных классов задач, подходят разные решения. Если говорить о Delphi, то для класса задач асинхронного ожидания ответа или исполнения лучше подходят TTask. Для класса задач распараллеливания лучше подходит TParallel. Для класса задач фонового (долгого, постоянного, возможно на время жизни всего приложения) выполнения (То о чем тут чаще всего говорят) к сожалению нет никакого BackgroundService который бы умел и зависимости разруливать и шедулер иметь нормальный и прочее, но из того что есть лучше подходит как раз TThread. На самом деле TThread - это класс для выполнения фоновых (долгоиграющих) задач. Если говорить о теме топика, то я не понимаю что такое многопоточное программирование. Есть решение задач с помощью потоков - это уже звучит по другому. И как минимум понятно, что не все задачи можно и нужно решать с помощью потоков. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.07.2020, 10:38 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Дегтярев Евгений пропущено... ты про шедулершедулер или gc? Раньше кооперативный планировщик был, а работу планировщика ОС они грубо говоря игнорировали. Теперь учитывают. видимо у авторов были веские причины запилить это, но как по мне оно решает настолько нетипичную для гошного кода ситуацию ... |
|||
:
Нравится:
Не нравится:
|
|||
09.07.2020, 20:03 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
У меня ощущение, что многие критикующие пропустили важные слова - "для начинающих". ... |
|||
:
Нравится:
Не нравится:
|
|||
10.07.2020, 00:16 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite Если говорить о теме топика, то я не понимаю что такое многопоточное программирование. Есть решение задач с помощью потоков - это уже звучит по другому. И как минимум понятно, что не все задачи можно и нужно решать с помощью потоков. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.07.2020, 08:32 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
X-Cite Проблема в Дельфи в том, что разработчики которые туда пытаются придти учатся по книжкам которые написаны были во времена высокого порога входа в программирование, а не когда курсы клепают по 100 "программистов" в день... Поэтому лучше, чтобы появлялись книжки, которые позволят вчерашним студентам, которые не знают как там работает под капотом, да и не надо им знать, но которые будут эффективно решать реальные бизнес-задачи используя современные инструменты. 1. проблема в том, что такие "программисты" никому и не нужны - если они не чисто за корочкой идут 2. нету реальных бизнес-задач с потоками, которые могут решать "прошедшие курсы" :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
10.07.2020, 08:38 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
wadman У меня ощущение, что многие критикующие пропустили важные слова - "для начинающих". просто пиписьками меряются друг перед другом. Другого объяснения нет ... |
|||
:
Нравится:
Не нравится:
|
|||
10.07.2020, 09:03 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer, я не уверен, но может быть при ручном убиении потока кошернее делать экземпляру потока не просто Free, а Free + Nil? Я обычно провожу проверку на существование предыдущего экземпляра прежде, чем запустить новый, типа: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
... |
|||
:
Нравится:
Не нравится:
|
|||
10.07.2020, 09:16 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док DmSer, я не уверен, но может быть при ручном убиении потока кошернее делать экземпляру потока не просто Free, а Free + Nil? Я обычно провожу проверку на существование предыдущего экземпляра прежде, чем запустить новый, типа: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Конечно, так и нужно. А в каком примере nil отсутствует? Вроде следил, чтобы везде было! ... |
|||
:
Нравится:
Не нравится:
|
|||
10.07.2020, 14:40 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer А в каком примере nil отсутствует? Код: pascal 1. 2. 3. 4. 5. 6. 7.
стр 16 ... |
|||
:
Нравится:
Не нравится:
|
|||
10.07.2020, 14:48 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док DmSer А в каком примере nil отсутствует? Код: pascal 1. 2. 3. 4. 5. 6. 7.
стр 16 Здесь нормально, тут же FormDestroy! Есть примеры, где объект потока уничтожается при нажатии на кнопку, вот там ссылка обнуляется и есть объяснение зачем это делается. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.07.2020, 15:31 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer, Респект за работу! Рекомендую назвать материал - "Памятка изучающим (многопоточное программирование на) Delphi TThread" (руки пока не дошли до описания темы синхронизации между потоками, а это, я считаю, очень важно). ... |
|||
:
Нравится:
Не нравится:
|
|||
11.07.2020, 19:49 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Bred eFeM Мдя... (может рассказать о нескольких способах кормления философов на примерах?) Я не уверен в пользе такого подхода. Помню, на 2-м или 3-м курсе университета были занятия, на которых преподавали многопоточность по философам ( библиотека Gala ), анимация интересная, но вряд ли кто-то из студентов смог извлечь из неё что-то полезное. А преподаватель вообще был не знаком с этой библиотекой :) ... |
|||
:
Нравится:
Не нравится:
|
|||
12.07.2020, 00:21 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Учебник сохранён в формате markdown. Очень удобная вещь оказалась. Текст в итоге читается вроде не хуже, чем в docx. ссылка ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2020, 20:05 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Не понравилось буквально в первом примере это: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8.
Как только начинающий захочет заменить MyShowMessage на показ своей супер-пупер формы - он может нехило обломаться. Обязательно надо подчеркнуть что все UI вещи (по крайней мере VCL) надо выполнить в Synchronize или Queue. Понятно что в примере голый WinApi и там и так прокатит, но лучше сразу показать. Вместо апишного вызова лучше взять делфёвый ShowMessage ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2020, 22:37 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
white_nigger Не понравилось буквально в первом примере это: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8.
Как только начинающий захочет заменить MyShowMessage на показ своей супер-пупер формы - он может нехило обломаться. Обязательно надо подчеркнуть что все UI вещи (по крайней мере VCL) надо выполнить в Synchronize или Queue. Понятно что в примере голый WinApi и там и так прокатит, но лучше сразу показать. Вместо апишного вызова лучше взять делфёвый ShowMessage В пояснении к этому примеру приводится необходимая информация о MyShowMessage и ShowMessage. Это сделано специально, чтобы читатель не пытался вызывать ShowMessage из доп. потока. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2020, 23:53 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Пробежал по диагонали. Классная статья получилась. Для полноты картины еще бы неплохо добавить разделы про эвенты, мьютексы, семафоры. Я, например, про эвенты кое-как наскреб инфу в инете, потому методом проб и ошибок дотумкал, как они работают :) ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 14:28 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док Пробежал по диагонали. Классная статья получилась. Для полноты картины еще бы неплохо добавить разделы про эвенты, мьютексы, семафоры. Я, например, про эвенты кое-как наскреб инфу в инете, потому методом проб и ошибок дотумкал, как они работают :) Спасибо! Эвенты, мьютексы и семафоры - очень сложная часть. Пока не придумал, как это влить в статью. Мьютексы может сейчас и не особенно актуальны. На своей практике могу сказать, что мьютексы полезны в случае, если нужно синхронизировать работу нескольких экземпляров программы (в том числе реализовать контроль повторного запуска приложения). В рамках одной программы они не нужны, можно их заменить крит. секцией либо TMonitor. Эвенты чаще используем, но только в рамках одной программы (т.е. без межпроцессного взаимодействия). В основном в обмене по RS-232. TMonitor их также может заменить. Семафоры вообще не используем, имхо, проще использовать крит.секцию + счётчик чем разбираться с ещё одним объектом синхронизации. Нужно ещё учитывать кроссплатформенность, иначе можно кучу времени потратить на то, что является сложным, windows-ориентированным и никому не нужным. Раньше я очень часто использовал эвенты, мьютексы, может даже злоупотреблял ими в какой-то степени. Сейчас гораздо реже. Выяснилось, что очень многие вещи можно сделать на крит. секции и циклах ожидания со Sleep :). Может так получается небольшой оверхед, но программа становится проще. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 15:42 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer и, как минимум, реализовать override-метод Execute. и, как минимум, переопределить виртуальный метод Execute. DmSer⚠️ Запущенный поток не завершается при выходе из программыЗавершается Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
Но до выделенной строки дело может не дойти из-за финализации менеджера памяти. Но я о чем - в Windows процесс живет, пока работает хотя бы один поток процесса, тогда как Delphi принудительно убивает процесс при завершении главного потока DmSerВаша программа с большой вероятностью будет глючить.Может имеет смысл обойтись без сленга? DmSerТакже хочу отметить, что при срабатывании таймера не следует обращаться к базе данных из основного потока, лучше это делать из дополнительного потока, разумеется, в отдельном подключении .Если мы говорим о мануале для новичков, то нифига это не разумеется. Если уже зацепил работу с БД, то явно укажи, что делать только так или смотреть документацию к СУБД. Тот же MySQL позволяет расшаривать соединение между потоками, при выполнении определенных условий DmSerℹ️ Внимание! Если периодическая задача выполняется редко (например, каждые 10 минут), рекомендуется каждый раз (если это не сложно!) для такой задачи создавать новый поток. Вероятно, это лучше, чем часами удерживать дополнительный поток в спящем состоянии (особенно, если вы разрабатываете 32-разрядное Windows-приложение).Чем лучше? Я бы наоборот делал бы обратную рекомендацию. Спящий поток есть не просит, а снаружи лучше управлять одним объектом, чем каждый раз создавать новый. Плюс дополнительное время на инициализацию нового потока DmSer⚠️ Внимание! Если поток переведён в спящее состояние с помощью функции Sleep, то не существует другого способа выйти из этого состояния кроме истечения указанного временного периодаТак зачем учить плохому? Есть две функции, которые можно использовать исключительно в тестовых приложениях и никогда в реальных Sleep() и Application.ProcessMessages. Новичкам об этих функциях вообще лучше не знать ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 16:17 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Код: pascal 1. 2. 3. 4. 5. 6. 7.
Ну и в чем великий смысл выделенной строчки? Если Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9.
... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 16:22 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSerЕсли же мы решим объявить для такого потока переменную и будем пытаться с нею работать, то рискуем нарваться на ошибку доступа к памяти «Access Violation», поскольку объект потока может быть уничтожен в любой момент времени.Верно только для случая, когда поток завершается сам ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 16:49 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSerи, как минимум, реализовать override-метод Execute. _Vasilisk_и, как минимум, переопределить виртуальный метод Execute. А точно между этими двумя вариантами выражения есть какая-то разница? На мой взгляд, оба варианта равноценны. Если человек понимает, что такое виртуальный метод, то он также знает что такое override-метод. _Vasilisk_> Ваша программа с большой вероятностью будет глючить. Может имеет смысл обойтись без сленга? Что здесь является сленгом? Слово "глючить"? Вроде нормальный термин для программистов. Да и статья не академическая. _Vasilisk_> Также хочу отметить, что при срабатывании таймера не следует обращаться к > базе данных из основного потока, лучше это делать из дополнительного потока, > разумеется, в отдельном подключении. Если мы говорим о мануале для новичков, то нифига это не разумеется. Если уже зацепил работу с БД, то явно укажи, что делать только так или смотреть документацию к СУБД. Тот же MySQL позволяет расшаривать соединение между потоками, при выполнении определенных условий Я согласен. По поводу работы с базой данных обязательно напишу отдельный раздел. Считаю это очень важным. Тем более работа с базами данных - это наиболее популярная область использования Дельфи. Есть большое количество наработок в этой часть. Есть что написать. _Vasilisk_> ℹ️ Внимание! Если периодическая задача выполняется редко (например, > каждые 10 минут), рекомендуется каждый раз (если это не сложно!) для > такой задачи создавать новый поток. Вероятно, это лучше, чем часами > удерживать дополнительный поток в спящем состоянии (особенно, если > вы разрабатываете 32-разрядное Windows-приложение). Чем лучше? Я бы наоборот делал бы обратную рекомендацию. Спящий поток есть не просит, а снаружи лучше управлять одним объектом, чем каждый раз создавать новый. Плюс дополнительное время на инициализацию нового потока Спящий поток кушает примерно 1,3 МБ адресного пространства (при условии, что 32-разрядная программа запущена на 64-разрядной винде). Это весьма много, ведь 32-разрядной программе доступно всего 2 ГБ под собственные нужны. Стоит лишь открыть TOpenDialog, так на тебе, сразу 300МБ уплыло. Используешь TWebBrowser, так ещё минус 200МБ. А что остаётся? _Vasilisk_Ну и в чем великий смысл выделенной строчки? Если Это приём, направленный на повышение читаемости кода. Там же чуть ниже отмечено, для чего так сделано. _Vasilisk_Верно только для случая, когда поток завершается сам Именно так! ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 17:26 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
InterlockedIncrement/InterlockedDecrement я бы заменил на кроссплатформенные AtomicIncrement/AtomicDecrement DmSer Код: pascal 1. 2. 3. 4. 5. 6. 7. 8.
DmSerНа главной форме находится таймер, который через определённые промежутки времени (каждые 100 мс) считывает из объекта-потока FMyThread свойства CalcResult, CurrValue и ThreadStateInfoИ рискуем получить несогласованные данные. DmSerprocedure TMyThread.SetThreadStateInfo(const Value: string); begin StringProtectSection.Enter; // Входим в режим защиты FThreadStateInfo := Value; StringProtectSection.Leave; // Выходим из режима защиты end;try finally всегда. Даже если внутри одна строчка. Ну и использование одной глобальной критической секции на все - это огромный антипаттерн DmSer⚠️ Внимание! Если строка (структура, объект, массив) является «константной», т.е. если значение присваивается лишь один раз и больше не меняется, то нет смысла её защищать!Это неверно. При чтении управляемых объектов изменяется счетчик ссылок тынц DmSerб) освобождается память, занятая старой строкой (с помощью функции менеджера памяти FreeMem). Память будет освобождена при условии, если старая строка нигде больше не используется, т.е. у неё нулевой счётчик ссылок.Как громоздко. У строки уменьшается счетчик ссылок. Если он достиг значения 0, то память освобождается DmSer⚠️ Внимание! Если Вы вводите свои (нестандартные коды сообщений), то необходимо использовать коды не менее WM_USER,WM_APP. Потому, что WM_USER + XXX VCL резервирует для себя. И можно нарваться ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 17:28 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer он также знает что такое override-метод. DmSer Спящий поток кушает примерно 1,3 МБ адресного пространства Код: 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.
Код: plaintext 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 17:48 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer В некоторых задачах (например, при математических вычислениях) следует по возможности избегать использования конструкций try..finally и try..except, т.к. они могут нести значительные накладные расходы.Шта? DmSer Код: pascal 1. 2. 3. 4. 5. 6. 7. 8.
1. И получить в конце ругань от менеджера памяти об утечках 2. Form1 может оказаться не главной формой и приложение может не завершиться DmSer Относительный приоритет потока работает только в рамках процесса и никак не влияет на выделение квантов времени потокам, которые работают в других процессах.MSDN с тобой не согласен https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority#remarks The SetThreadPriority function enables setting the base priority level of a thread relative to the priority class of its process. For example, specifying THREAD_PRIORITY_HIGHEST in a call to SetThreadPriority for a thread of an IDLE_PRIORITY_CLASS process sets the thread's base priority level to 6. Ну и нет главы о передаче данных в дополнительный поток ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 18:17 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
_Vasilisk_ DmSer В некоторых задачах (например, при математических вычислениях) следует по возможности избегать использования конструкций try..finally и try..except, т.к. они могут нести значительные накладные расходы. Код: 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.
Код: plaintext
... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 18:33 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
_Vasilisk_ DmSer Спящий поток кушает примерно 1,3 МБ адресного пространства Код: 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.
Код: plaintext 1. 2.
Причём тут pagefile? Речь же шла про виртуальное адресное пространство! ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 19:36 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
_Vasilisk_ _Vasilisk_ пропущено... Шта? Код: 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.
Код: plaintext
Операция операции рознь. Чем тяжелее операция тем меньше разница. Отказываться от обработки ошибок не нужно. Но и совать её куда ни попадая не следует. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 19:43 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
_Vasilisk_DmSerprocedure TMyThread.SetThreadStateInfo(const Value: string); begin StringProtectSection.Enter; // Входим в режим защиты FThreadStateInfo := Value; StringProtectSection.Leave; // Выходим из режима защиты end;try finally всегда. Даже если внутри одна строчка. Ну и использование одной глобальной критической секции на все - это огромный антипаттерн try..finally ради одной безобидной строчки выглядит как-то нерационально. Какой в ней смысл? Кто такое правило ввёл? Про критическую секцию согласен. Однако в плане обучения я посчитал такой подход проще, удобнее, понятнее. И я не сразу ввожу термин "критическая секция", а постепенно. Иначе у начинающего каша в голове будет и он бросит всё это читать. _Vasilisk_DmSer Внимание! Если строка (структура, объект, массив) является «константной», т.е. если значение присваивается лишь один раз и больше не меняется, то нет смысла её защищать!Это неверно. При чтении управляемых объектов изменяется счетчик ссылок тынц Счётчик ссылок может изменяться из разных потоков. Это безопасно в том случае, если строка не меняется. _Vasilisk_DmSerВнимание! Если Вы вводите свои (нестандартные коды сообщений), то необходимо использовать коды не менее WM_USER,WM_APP. Потому, что WM_USER + XXX VCL резервирует для себя. И можно нарваться Фантазии какие-то! Назови хоть один случай, где WM_USER+1 не работал! А ещё огласи, чему равен тот загадочный XXX? ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 21:38 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
_Vasilisk_ DmSer Относительный приоритет потока работает только в рамках процесса и никак не влияет на выделение квантов времени потокам, которые работают в других процессах. Действительно я накосячил. Исправил. Доработал программу для исследования квантов и приоритетов. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2020, 22:13 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Фантазии какие-то! Назови хоть один случай, где WM_USER+1 не работал! А ещё огласи, чему равен тот загадочный XXX? http://delphimaster.net/view/1-59239 ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 07:26 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Еще поправил раздел о приоритетах спорная часть теперь выглядит так: Обычно программисту нет смысла изменять приоритеты потоков. Приоритет потока никак не влияет на скорость исполнения программного кода. Приоритет потока никак не влияет на размер кванта времени (однако размер кванта времени зависит от того, является ли приложение активным или нет). :information_source: **Внимание!** У приложения, которое находится на переднем плане, длительность кванта времени увеличивается примерно в 3 раза (это не имеет отношения к базовому приоритету процесса). Одну и ту же вычислительную задачу быстрее (примерно в 3 раза) сможет решить приложение, которое находится на переднем плане. На моих компьютерах с Windows 7 длительность кванта времени у приложений на заднем плане (думаю, что и у служб тоже) составляет 32 мс, а у приложений на переднем плане - 96 мс. Относительный приоритет потока влияет на выделение процессорного времени как между потоками в рамках одного процесса, так и между потоками различных процессов. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 08:40 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
istrebitel DmSer Фантазии какие-то! Назови хоть один случай, где WM_USER+1 не работал! А ещё огласи, чему равен тот загадочный XXX? http://delphimaster.net/view/1-59239 Думаю, что WM_USER+100 нужен при разработке наследников от некоторых компонентов. А лучше изучать исходники и смотреть, какие коды там используются. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 08:47 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Одну и ту же вычислительную задачу быстрее (примерно в 3 раза) сможет решить приложение, которое находится на переднем плане. Исправлено: В том случае, если два приложения будут привязаны к одному ядру процессора, то одну и ту же вычислительную задачу быстрее (примерно в 3 раза) сможет решить приложение, которое находится на переднем плане. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 09:14 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 09:46 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Как-то странно это работает. Поставил приоритет для служб в фоновом режиме, теперь квант у обычных программ резко подрос и стал около 195 мс. Причем теперь он у всех одинаковый и не зависит от того, на переднем плане программа или на заднем плане. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 12:37 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer, Да, про увеличение размера кванта написано у Русиновича, кажется (Внутреннее устройство Windows). ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 12:45 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Кстати, величина самого длинного кванта на Windows 2000 всего 36. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 13:01 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Счётчик ссылок может изменяться из разных потоков. Это безопасно в том случае, если строка не меняется. Ладно. Я все понял. Твой подход: "зачем делать правильно если в конкретном частном случае работает и так?". Только программа имеет тенденцию развиваться и мне проще изначально писать правильно, чем потом выискивать места, где нужно что-то поправить ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 15:01 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
_Vasilisk_ DmSer Счётчик ссылок может изменяться из разных потоков. Это безопасно в том случае, если строка не меняется. Речь идёт о "константной" строке, значение которой присваивается один раз и больше не меняется. Счётчик станет нулём в том случае, если строка никому больше не нужна. В этом случае строка будет уничтожена, память освободится. Никаких проблем с многопоточным доступом тут нет. Конечно, можно на всякий случай каждую строчку кода защищать критической секцией и для каждой строки на всякий случай вызывать UniqueString. Но зачем? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 16:10 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer _Vasilisk_ пропущено... Счетчик ссылок может стать нулем Речь идёт о "константной" строке, значение которой присваивается один раз и больше не меняется. Счётчик станет нулём в том случае, если строка никому больше не нужна. В этом случае строка будет уничтожена, память освободится. Никаких проблем с многопоточным доступом тут нет. Конечно, можно на всякий случай каждую строчку кода защищать критической секцией и для каждой строки на всякий случай вызывать UniqueString. Но зачем? Сколько интересных граблей необходимо помнить и обходить, если вместо подходящих инструментов и подходов использовать базовые... На моей памяти уже несколько лет не было случая, чтобы что-то блокировать, кроме очередей. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2020, 19:35 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Добавлена информация о threadvar и немного о UniGui. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.08.2020, 00:02 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Кстати, если интересно, вот тут https://forum.lazarus.freepascal.org/index.php/topic,40163.msg277111.html#msg277111 многие из авторов рекомендуют пользоваться Synchronize/Queue взамен привычных для винды SendMessage/PostMessage. Правда, это для Лазаря и с учетом кроссплатформенности. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 17:06 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док Кстати, если интересно, вот тут https://forum.lazarus.freepascal.org/index.php/topic,40163.msg277111.html#msg277111 многие из авторов рекомендуют пользоваться Synchronize/Queue взамен привычных для винды SendMessage/PostMessage. Правда, это для Лазаря и с учетом кроссплатформенности. Только с некой оговоркой, как у меня. Синхронизация с главным потоком происходит через посредника - отдельного потока, которым пользуются все остальные. Так я избавляюсь от ожидания. Сказал посреднику, что хочешь сообщить главному и дальше пошел работать. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 21:07 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док Кстати, если интересно, вот тут https://forum.lazarus.freepascal.org/index.php/topic,40163.msg277111.html#msg277111 многие из авторов рекомендуют пользоваться Synchronize/Queue взамен привычных для винды SendMessage/PostMessage. Правда, это для Лазаря и с учетом кроссплатформенности. и на это есть много причин ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 09:25 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
kealon(Ruslan) и для VCL я это советую И не знаешь, кого слушать :) Это как с Application.ProcessMessages - все кричат, что его применение - моветон и чревато страшными багами, а на деле - вероятность можно на пальцах посчитать ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 14:44 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
wadman Так я избавляюсь от ожидания. сложно это все. Я проще поступаю: если надо дождаться в доп.потоке реакции от главного - делаю Synchronize/SendMessage, если пофиг - Queue/PostMessage :) ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 14:46 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Докесли надо дождаться в доп.потоке реакции от главного - делаю Synchronize/SendMessage В моё время Synchronize не принимал параметры и не позволял вернуть значение, приходилось всё делать через левые переменные. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 15:01 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док kealon(Ruslan) и для VCL я это советую И не знаешь, кого слушать :) Это как с Application.ProcessMessages - все кричат, что его применение - моветон и чревато страшными багами, а на деле - вероятность можно на пальцах посчитать а на деле вопрос получения трудновыловимых багов от Application.ProcessMessages в случае многопоточного приложения - это вопрос времени. А первый раз, не зная куда копать - можно очень долго искать причину. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 16:00 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Vizit0r а на деле вопрос получения трудновыловимых багов от Application.ProcessMessages в случае многопоточного приложения - это вопрос времени. да расслабьтесь, я его втыкаю только в тестовых приложениях :) ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 17:05 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док, я из своего опыта просто делюсь... ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 17:46 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Vizit0r Док пропущено... И не знаешь, кого слушать :) Это как с Application.ProcessMessages - все кричат, что его применение - моветон и чревато страшными багами, а на деле - вероятность можно на пальцах посчитать а на деле вопрос получения трудновыловимых багов от Application.ProcessMessages в случае многопоточного приложения - это вопрос времени. А первый раз, не зная куда копать - можно очень долго искать причину. Неоднократно сталкивался с проблемами, которые проявлялись при использовании Application.ProcessMessages. Поэтому в "учебнике" никому советовать использовать Application.ProcessMessages не буду. Например, были попытки с помощью Application.ProcessMessages организовать цикл ожидания окончания работы дополнительного потока. Получается фигня. Лучше модальное окно показать с какой-нибудь анимацией и закрывать его при окончании работы потока. Причем модальное окно можно делать невидимым первые 5 секунд. Позже я опишу этот приём в "учебнике". ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 23:23 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer были попытки с помощью Application.ProcessMessages организовать цикл ожидания окончания работы дополнительного потока ProcessMessages нужен для того что бы интерфейс не залипал при длительной работе в основном потоке. Да и то надо в уме держать возможные побочные эффекты, и например, отключать ненужные возможности по вводу данных в GUI. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 23:48 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
rgreat DmSer были попытки с помощью Application.ProcessMessages организовать цикл ожидания окончания работы дополнительного потока ProcessMessages нужен для того что бы интерфейс не залипал при длительной работе в основном потоке. Да и то надо в уме держать возможные побочные эффекты, и например, отключать ненужные возможности по вводу данных в GUI. Я уже как-то рассказывал, в этом году обнаружил код в нашем ПО, в котором запускался доп. поток для формирования отчета и выполнялось ожидание окончания формирования отчёта с помощью цикла: Код: pascal 1. 2. 3. 4. 5.
В случае, если сервер отчётов находился не в локальной сети, а где-то в сети интернет, то метод ProcessMessages не возвращал управление (но GUI при этом обновлялся). Детально не разбирался, почему так. Просто реализовал ожидание с помощью модальной формы и теперь никаких зависаний нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2020, 08:37 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer rgreat пропущено... Нафига, если есть Timer и Event-ы? ProcessMessages нужен для того что бы интерфейс не залипал при длительной работе в основном потоке. Да и то надо в уме держать возможные побочные эффекты, и например, отключать ненужные возможности по вводу данных в GUI. Я уже как-то рассказывал, в этом году обнаружил код в нашем ПО, в котором запускался доп. поток для формирования отчета и выполнялось ожидание окончания формирования отчёта с помощью цикла: Код: pascal 1. 2. 3. 4. 5.
В случае, если сервер отчётов находился не в локальной сети, а где-то в сети интернет, то метод ProcessMessages не возвращал управление (но GUI при этом обновлялся). Детально не разбирался, почему так. Просто реализовал ожидание с помощью модальной формы и теперь никаких зависаний нет. О, господи. Мне кажется, правильнее было бы реализовать "ожидание" убрав формирование отчета из доп потока в главный. Раз уж зачем-то нужно "ожидание". ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2020, 09:33 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
YuRock Мне кажется, правильнее было бы реализовать "ожидание" убрав формирование отчета из доп потока в главный. Раз уж зачем-то нужно "ожидание". В нашем случае ПО управляет ещё кучей устройств, главный поток дёргается постоянно, поэтому мы не можем надолго его блокировать. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2020, 09:53 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer запускался доп. поток для формирования отчета и выполнялось ожидание окончания формирования отчёта с помощью цикла: а в доп.потоке -то оно зачем? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2020, 18:00 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Hi Во-первых, хочу по-приветствовать идею написания книги, выразить моральную поддержку и пожелать творческих успехов. Во-вторых, позволь внести пару предложений. В разделе 1.2. надо как-то более сжато выделить проблемы и требования к многопоточным приложениям. Что-то типа этого: 1. Библиотеки графических компонентов (как VCL так и FMX) способны корректно работать только в основном потоке, обращение к ним напрямую из любых других потоков недопустимо (как допустимо будет сказано ниже). 2. Обращение к данным внутри потока напрямую также недопустимо, так как в любой случайный момент времени данные могут быть еще полностью не сформированы, память не выделена, или уже уничтожена. 3. Многие не графические компоненты скрыто взаимодействуют между собой и графическим интерфейсом приводя к нарушениям требований 1 и 2. Например: TSQLConnection, TSQLDataSet, TDataSource и TDBEdit. 4. Требования из предыдущих пунктов ни как не контролируется средой разработки и требует особой внимательности разработчика. При этом ошибки носят вероятностный характер. Зачастую возможность появления ошибки зависит от скорости работы процессора, заполненности памяти, скорости работы сети и т.п. 5. Даже в случае правильной и безошибочной работы приложения не всегда возможна подлинная многозадачность. Например: выполнение длительных запросов в рамках одной сессий Oracle не может выполняться параллельно, т.е. запустив выполнение длительного запроса в отдельном потоке пользователь тем не менее всё равно не сможет полноценно работать с данными. Когда вы собираетесь выносить часть кода в отдельный поток следует обратить внимание на следующие моменты: 1. Необходимо максимально сократить доступ к графическому интерфейсу, в идеале совсем исключить. 2. Необходимо максимально изолировать код внутри потока. Например: создаем модуль данных, подключаемся к БД, выполняем запрос, записываем результаты выполнения, разрушаем модуль данных. 3. Обязательно надо убедиться в потокозащищенности используемых в потоке компонентов. Причем декларируемая потокозащищенность не всегда соответствует действительности. 4. Следует убедиться в наличие достаточных человеческих ресурсов. Отладка будет на порядок сложнее, подумайте еще раз стоит ли игра свеч? Может целесообразней вынести долгое вычисление в отдельное приложение? Нужна ли действительно постоянная активность графического интерфейса, или достаточно простого окна ожидания? Возможно стоит вынести код не в отдельный поток а в отдельное небольшое консольное приложение. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2020, 18:27 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
roschinspb, Спасибо за предложения! Я их проанализирую и постараюсь отразить в статье. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2020, 19:30 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
roschinspb, Сереж, у тебя же на "народе" небольшая статья была с примерами потоков... ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2020, 23:09 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
roschinspb, автор4. Следует убедиться в наличие достаточных человеческих ресурсов. Отладка будет на порядок сложнее, подумайте еще раз стоит ли игра свеч? Может целесообразней вынести долгое вычисление в отдельное приложение? Нужна ли действительно постоянная активность графического интерфейса, или достаточно простого окна ожидания? я бы не сказал, что так уж сложно и на порядок. достаточно придерживаться известных принципов: не лезть к vcl и к расшаренным ресурсам и в 99% случаев всё сразу же заработает. невизуальные компоненты, имеющие проблемы в многопоточке - скорее исключение. долгие вычисления как правило предполагают много данных и гонять данные между приложениями в обе стороны - то еще удовольствие ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 09:14 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
makhaon, не так уж и сложно гонять. доп процесс полезен если используются сторонние библиотеки, которые могут привести к зависанию программы. пришлось так делать когда использовал bass что бы писать интернет радио... ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 09:35 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Zelius makhaon, не так уж и сложно гонять. доп процесс полезен если используются сторонние библиотеки, которые могут привести к зависанию программы. пришлось так делать когда использовал bass что бы писать интернет радио... это скорее исключение. А в целом - гораздо полезнее разобраться с потоками, чем с межпроцессным взаимодействием. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 10:30 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Vizit0r, полезнее знать что делать, когда программа виснет в чужой dll и никакие потоки не спасают, т.к. их не перезапустить... ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 11:22 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Zelius makhaon, не так уж и сложно гонять. доп процесс полезен если используются сторонние библиотеки, которые могут привести к зависанию программы. пришлось так делать когда использовал bass что бы писать интернет радио... К сожалению, межпроцессное взаимодействие это не та задача, которая возникает у большинства Delphi-программистов каждый день. В RTL, если не ошибаюсь, нет практически ничего готового в помощь для решения этой задачи (я не говорю о взаимодействии по TCP или через COM, тут как раз более менее всё необходимое имеется). Если возникает задача организовать взаимодействие между процессами в рамках одного компьютера, то, думаю, каждый Delphi-программист вынужден мастерить свой велосипед. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 12:08 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
roschinspb, а где предложение про Окно, отображающее ход выполнения длительной операции ? :) Было бы уместным! С ним кстати не было проблем/сбоев? Работает во всех версиях Delphi? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 12:16 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Так или иначе, "учебник" в первую очередь о том, как научиться многопоточному программированию в Delphi (в идеале, для решения различных задач, где уместна многопоточность), а не о том, как решать различные задачи, не прибегая к многопоточному программированию. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 12:20 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Zelius Vizit0r, полезнее знать что делать, когда программа виснет в чужой dll и никакие потоки не спасают, т.к. их не перезапустить... это уже сильно частные случаи, на самом деле. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 13:37 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer roschinspb, а где предложение про Окно, отображающее ход выполнения длительной операции ? :) Было бы уместным! С ним кстати не было проблем/сбоев? Работает во всех версиях Delphi? Для начинающих пример сложноват. Это скорее для второго тома. Многопоточное программирование для тех, кто бросает. 😁. Вообще на сайте не последняя версия. Последняя с исправлениями для 64 бит погибла вместе с винчестером. Когдато яя её кому-то выслал, может где и есть еще. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 15:32 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
makhaon невизуальные компоненты, имеющие проблемы в многопоточке - скорее исключение Я не знаю какая у тебя предметная область... у меня всякие клиент-серверные приложения, весьма крупные. И вот сколько бы контор не сменил почти во всех натыкался на решения " а не выполнить ли мне долгие запросы в отдельном потоке ". И использовать какраз компоненты имеющие проблемы в многопоточке и которые обращаются к графическому интерфейсу скрыто от глаз молодого бойца. Описание проблемы в терминах тестировщика типа: " вот чето у нас всё работает, а у клиентов... у некоторых... иногда зависает в непонятных местах ". Код хорошо характеризует высказывание одного патологоанатома: В нашем морге последними словами 40% клиентов было "Гляди посоны как я могу!", а половина клиентов последнее что сказала "Не, дай я покажу как надо!". Почти всегда исправление заключается в тупом переносе кода в основной поток. Прогрессбар можно перерисовать и repaint-ом, а обеспечивать реальную параллельную работу пользователя и так не требовалось. makhaon долгие вычисления как правило предполагают много данных и гонять данные между приложениями в обе стороны - то еще удовольствие P.S. Я не призываю отказаться от тредов вообще и не надо меня убеждать в том что иногда они нужны. Я просто пытаюсь избавить от лишних проблем начинающих программеров и тех кто потом за ними будет код чистить. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.08.2020, 17:43 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Так вот кто гуглу насоветовал про процессы, так что теперь хром плодит свои копии интенсивней, чем зерглинги вылупляются! ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 00:40 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Fr0sT-Brutal теперь хром плодит свои копии интенсивней, чем зерглинги вылупляются! 146%! И на старых машинах иногда завешивает проц вусмерть. roschinspb Прогрессбар можно перерисовать и repaint-ом если только в таймере. Интересно, сколько таймеров можно запустить без заметного вреда для софтины? ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 08:32 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
мне кажется эта статья описывает многопоточность достаточно хорошо, многое оттуда взять можно https://forum.vingrad.ru/topic-60076.html ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 08:45 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
cptngrb мне кажется эта статья описывает многопоточность достаточно хорошо, многое оттуда взять можно https://forum.vingrad.ru/topic-60076.html Да, я с нею знакомился. Она не для начинающих. Писалась в те времена, когда программирование было уделом гениев. Очень тяжело усваивается. Думаю, мало кто осилит дочитать более 30% (до БАБ врядли дело дойдет :) ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 10:36 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Zelius ... пришлось так делать когда использовал bass что бы писать интернет радио... ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2020, 18:50 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док . Интересно, сколько таймеров можно запустить без заметного вреда для софтины? ... |
|||
:
Нравится:
Не нравится:
|
|||
09.08.2020, 04:16 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Добавлен раздел планирование потоков ... |
|||
:
Нравится:
Не нравится:
|
|||
09.08.2020, 10:56 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Может пригодиться и такая инфа: CAS https://ru.wikipedia.org/wiki/Сравнение_с_обменом FAA https://en.wikipedia.org/wiki/Fetch-and-add ... |
|||
:
Нравится:
Не нравится:
|
|||
09.08.2020, 18:01 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
spinlock https://ru.wikipedia.org/wiki/Спин-блокировка I/O Completion Ports https://docs.microsoft.com/en-us/windows/win32/fileio/i-o-completion-ports ------ Не всем, и не всегда нужна кроссплатформенность. Бывает, что важнее выжать по-максимуму из возможностей ОС и процессора. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.08.2020, 18:15 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
s62, Использовал чтото высокоуровневое, просто урл передавал, под капот потока не смотрел ... |
|||
:
Нравится:
Не нравится:
|
|||
09.08.2020, 21:11 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Док, зы. на скруле всегда так, как только тема исчерпывается, начинается оффтоп Рано! Кучу материалов изучаю по многопоточности. Что-нибудь получится! :) ... |
|||
:
Нравится:
Не нравится:
|
|||
13.08.2020, 18:10 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer cptngrb мне кажется эта статья описывает многопоточность достаточно хорошо, многое оттуда взять можно https://forum.vingrad.ru/topic-60076.html Да, я с нею знакомился. Она не для начинающих. Писалась в те времена, когда программирование было уделом гениев. Очень тяжело усваивается. Думаю, мало кто осилит дочитать более 30% (до БАБ врядли дело дойдет :) На мой взгляд неплохо или просто хорошо :) написано у Пачеко и Тексейры https://www.for-stydents.ru/informatika/delphi/uchebniki/delphi-5-rukovodstvo-razrabotchika-tom-1-osnovnye-metody-i-tehnologii-programmirovaniya.html Хотя книжка старая, 2000 года. Глава 11 "Создание многопоточных приложений". По-моему довольно простое, понятное изложение, при этом затронуты разные темы, в том числе многопоточный доступ к БД, графика. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2020, 13:31 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Переработан раздел Планирование потоков Пришлось убрать раздел "Роль кэшей процессора", т.к. выяснилось, что кэши процессора практически не играют никакой роли в планировании потоков и переключении контекста, а парить читателю мозги лишней информацией я не хочу. Кто в теме разбирается, посмотрите на предмет того, чтобы не было дезинформации. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2020, 14:56 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer, warning Внимание! Согласно официальной документации, в секции threadvar нельзя объявлять переменные некоторых типов, в том числе: Pointer, Function, а также типы, работающие по принципу copy-on-write, например string. Где это такие глупости написаны??? Официальная дока: http://docwiki.embarcadero.com/RADStudio/Rio/en/Variables_(Delphi)#Thread-local_Variables Thread-variable declarations: cannot occur within a procedure or function. cannot include initializations. cannot specify the absolute directive. Dynamic variables that are ordinarily managed by the compiler (long strings, wide strings, dynamic arrays, variants, and interfaces) can be declared with threadvar, but the compiler does not automatically free the heap-allocated memory created by each thread of execution. If you use these data types in thread variables, it is your responsibility to dispose of their memory from within the thread, before the thread terminates. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2020, 15:25 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Kazantsev Alexey DmSer, warning Внимание! Согласно официальной документации, в секции threadvar нельзя объявлять переменные некоторых типов, в том числе: Pointer, Function, а также типы, работающие по принципу copy-on-write, например string. Где это такие глупости написаны??? Официальная дока: http://docwiki.embarcadero.com/RADStudio/Rio/en/Variables_(Delphi)#Thread-local_Variables Thread-variable declarations: cannot occur within a procedure or function. cannot include initializations. cannot specify the absolute directive. Dynamic variables that are ordinarily managed by the compiler (long strings, wide strings, dynamic arrays, variants, and interfaces) can be declared with threadvar, but the compiler does not automatically free the heap-allocated memory created by each thread of execution. If you use these data types in thread variables, it is your responsibility to dispose of their memory from within the thread, before the thread terminates. Я взял это несколько недель назад из их официальной документации, по той же ссылке. Видимо, уже успели поменять. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2020, 16:32 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Я взял это несколько недель назад из их официальной документации. Видимо, уже успели поменять. Сходи по ссылке и посмотри дату последней модификации страницы. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2020, 16:37 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2020, 16:44 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Kazantsev Alexey, Такой значит у них бардак в документации. Хорошо что заметили и поправили. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2020, 17:09 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Измерил, как зависит количество запущенных потоков на производительность. Запускал 100000 потоков (64-битный компилятор), в каждом лишь такой код: Код: pascal 1. 2.
Т.е. потоки тупо ничего не делают. Измерял число операций на 4-х ядрах до запуска и после запуска этих потоков. Выяснилось, что падение производительности составляет 6%. Хотя я думал, что будет намного хуже. Замеры делал с помощью "CalcTimeQuant.exe". Выяснилось, что 3 из 4-х ядер вообще не замечают этих спящих потоков и выдают максимальную производительность. Производительность падает грубо говоря только на одном ядре (видимо на нем и работает планировщик). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2020, 20:57 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Kazantsev Alexey, Такой значит у них бардак в документации. Хорошо что заметили и поправили. Ошибся. Ссылка не та все-таки. Использовал эту ссылку ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2020, 22:33 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Переработан раздел Планирование потоков Пришлось убрать раздел "Роль кэшей процессора", т.к. выяснилось, что кэши процессора практически не играют никакой роли в планировании потоков и переключении контекста, а парить читателю мозги лишней информацией я не хочу. Кто в теме разбирается, посмотрите на предмет того, чтобы не было дезинформации. Последний эксперимент дал новые идеи :) Я ещё раз переработал этот раздел! ... |
|||
:
Нравится:
Не нравится:
|
|||
16.08.2020, 00:05 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer, авторЯ предполагаю, что логика обработки прерывания от системного таймера примерно такая: системный таймер подаёт сигнал прерывания на все ядра процессора; приостанавливается работа всех выполняемых потоков на всех ядрах процессора; осуществляется запуск системного планировщика на одном из ядер процессора (Sheduler Core); Руссинович и Соломон пишут вот тут https://www.microsoftpressstore.com/articles/article.aspx?p=2233328&seqNum=7 , авторTo make thread-scheduling decisions, the kernel maintains a set of data structures known collectively as the dispatcher database, illustrated in Figure 5-15. The dispatcher database keeps track of which threads are waiting to execute and which processors are executing which threads. To improve scalability, including thread-dispatching concurrency, Windows multiprocessor systems have per-processor dispatcher ready queues, as illustrated in Figure 5-15. In this way each CPU can check its own ready queues for the next thread to run without having to lock the systemwide ready queues. (Versions of Windows before Windows Server 2003 used a global database). что, начиная с Windows server 2003 данные об очереди готовых к исполнению потоков у каждого процессора своя, так что они могут проверять каждый свою очередь, не блокируя очереди на уровне всей системы. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.08.2020, 12:38 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
s62 DmSer, авторЯ предполагаю, что логика обработки прерывания от системного таймера примерно такая: системный таймер подаёт сигнал прерывания на все ядра процессора; приостанавливается работа всех выполняемых потоков на всех ядрах процессора; осуществляется запуск системного планировщика на одном из ядер процессора (Sheduler Core); Руссинович и Соломон пишут вот тут https://www.microsoftpressstore.com/articles/article.aspx?p=2233328&seqNum=7 , авторTo make thread-scheduling decisions, the kernel maintains a set of data structures known collectively as the dispatcher database, illustrated in Figure 5-15. The dispatcher database keeps track of which threads are waiting to execute and which processors are executing which threads. To improve scalability, including thread-dispatching concurrency, Windows multiprocessor systems have per-processor dispatcher ready queues, as illustrated in Figure 5-15. In this way each CPU can check its own ready queues for the next thread to run without having to lock the systemwide ready queues. (Versions of Windows before Windows Server 2003 used a global database). что, начиная с Windows server 2003 данные об очереди готовых к исполнению потоков у каждого процессора своя, так что они могут проверять каждый свою очередь, не блокируя очереди на уровне всей системы. Классная статья! По ней убеждаюсь, что информация в моей статье в разделе "планирование потоков" более-менее корректная. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.08.2020, 18:31 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Классная статья! По ней убеждаюсь, что информация в моей статье в разделе "планирование потоков" более-менее корректная. Просто у этих ребят было добро на публикацию "инсайдерской" инфы от MыSы. Вот ты её же по кусочкам раньше и насобирал. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2020, 00:54 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
А я вот не понял п4.1 Зачем Sleep() обертывать в WaitTimeout ? авторwarning Внимание! Если поток переведён в спящее состояние с помощью функции Sleep, то не существует другого способа выйти из этого состояния кроме истечения указанного временного периода. И что тогда использовать вместо Sleep? ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 14:40 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
didgik И что тогда использовать вместо Sleep? Например в WaitFor*Object, у которого в аргументах событие, которому можно посигналить извне. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 15:24 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
wadman didgik И что тогда использовать вместо Sleep? Например в WaitFor*Object, у которого в аргументах событие, которому можно посигналить извне. Не очень понятно извне это из основного потока? Повесить там таймер и раз, допустим, в 10 мин. посылать сигнал? ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 16:16 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
didgik А я вот не понял п4.1 Зачем Sleep() обертывать в WaitTimeout ? Можно и не обертывать. В данном случае поведение программы от этого не изменится. Однако действие по ожиданию таймаута может быть более сложным, чем просто вызвать Sleep. В этом случае разумнее вынести код в отдельную функцию. В дальнейшем можно улучшить код в данной функции, не переделывая все места, из которых эта функция вызывается. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 16:55 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
didgik И что тогда использовать вместо Sleep? В некоторых случаях можно использовать более навороченную версию: ThreadWaitTimeout из модуля MTUtils.pas. Но в идеале следует использовать функцию WaitXXXXX ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 16:59 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
04.09.2020 16:59, DmSer пишет: > Но в идеале следует использовать функцию WaitXXXXX мотивируй Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 17:05 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer didgik И что тогда использовать вместо Sleep? В некоторых случаях можно использовать более навороченную версию: ThreadWaitTimeout из модуля MTUtils.pas. Но в идеале следует использовать функцию WaitXXXXX я, кстати, не нашел ThreadWaitTimeout в 2007. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 17:10 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Мимопроходящий 04.09.2020 16:59, DmSer пишет: > Но в идеале следует использовать функцию WaitXXXXX мотивируй Оверхед меньше по сравнению с sleep(10) в цикле. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 17:56 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
didgik DmSer пропущено... В некоторых случаях можно использовать более навороченную версию: ThreadWaitTimeout из модуля MTUtils.pas. Но в идеале следует использовать функцию WaitXXXXX я, кстати, не нашел ThreadWaitTimeout в 2007. Там её нет. Искать нужно там же где статья. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 18:10 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
didgik wadman пропущено... Например в WaitFor*Object, у которого в аргументах событие, которому можно посигналить извне. Не очень понятно извне это из основного потока? Повесить там таймер и раз, допустим, в 10 мин. посылать сигнал? Посылать сигнал только тогда, когда нужно. Будить таким образом поток, если нужно. А в Thread.Destroy сделать Terminate и SetEvent. А в потоке после ожидания проверять на Terminated. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2020, 20:56 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Мимопроходящий 04.09.2020 16:59, DmSer пишет: > Но в идеале следует использовать функцию WaitXXXXX мотивируй Оверхед меньше по сравнению с sleep(10) в цикле. Помимо меньшего оверхеда также следует отметить время реакции. Поток, остановленный по команде Sleep, может возобновить работу только после срабатывания системного таймера. А по умолчанию системный таймер срабатывает примерно раз в 16 миллисекунд. При ожидании на WaitForXXXXX возобновление работы происходит намного оперативнее. Идеальный случай, когда в момент вызова SetEvent / ReleaseMutex у планировщика есть возможность запустить ожидающий поток на том же ядре и отсутствуют другие желающие, кому требуется это же ядро. Тогда планировщик запускает ожидающий поток немедленно, не прибегая к системному таймеру или к механизму асинхронного вызова APC. На всё про всё уходит порядка 6 микросекунд (железо не самое мощное). Однако такое происходит редко, чаще планировщик запускает ожидающий поток с использованием механизма APC (с программным прерыванием), в этом случае уходит от 20 до 50 микросекунд (на моих тестах). Худший случай, когда механизм APC не смог запустить ожидаемый поток (мог вклиниться поток с более высоким приоритетом), тогда запуск ожидающего потока будет запланирован уже по событию системного таймера. Как-то так оно работает (в моём понимании). ... |
|||
:
Нравится:
Не нравится:
|
|||
05.09.2020, 23:45 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
За последнее время: 1. Добавлен раздел "1.2 Можно ли избежать многопоточного программирования", к нему пример ExNotUseThreads 2. Добавлен раздел "Основные объекты синхронизации в Windows" 3. Добавлен раздел "7.1 Главный поток управляет работой дополнительного потока с помощью объекта "Event" (событие)" и к нему пример FastStopThread 4. Добавлен пример SimpleLogger, который очень наглядно демонстрирует преимущество использования доп. потока при записи в лог-файл (соответствующее описание к данному примеру пока отсутствует). 5. Исправлено несколько замечаний, в том числе большая часть замечаний от _Vasilisk_ 6. Учтены некоторые предложения ... |
|||
:
Нравится:
Не нравится:
|
|||
23.11.2020, 08:53 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer 1. Добавлен раздел "1.2 Можно ли избежать многопоточного программирования", к нему пример ExNotUseThreads ... |
|||
:
Нравится:
Не нравится:
|
|||
23.11.2020, 23:19 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
А я вот просто хочу выразить признательность автору статьи! От "не новичка" в Delphi, но неработающего с потоками (пока). Периодически читаю что-то о потоках, т.к. сегодня не надо, а завтра... Такая статья очень поможет если вдруг "припрёт". Прочитал весь топик. Начну читать статью... Еще раз - автору спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.12.2020, 18:19 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Volk65 А я вот просто хочу выразить признательность автору статьи! От "не новичка" в Delphi, но неработающего с потоками (пока). Периодически читаю что-то о потоках, т.к. сегодня не надо, а завтра... Такая статья очень поможет если вдруг "припрёт". Прочитал весь топик. Начну читать статью... Еще раз - автору спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.12.2020, 20:29 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Volk65 А я вот просто хочу выразить признательность автору статьи! От "не новичка" в Delphi, но неработающего с потоками (пока). Периодически читаю что-то о потоках, т.к. сегодня не надо, а завтра... Такая статья очень поможет если вдруг "припрёт". Прочитал весь топик. Начну читать статью... Еще раз - автору спасибо. Спасибо, буду рад, если мои труды принесут для кого-то пользу! Добавлены следующие новые разделы: 7.2 Использование объекта "Event" для разработки потока логгирования ... 7.3 Пара слов об объекте "Mutex" ... 7.4 Пара слов об объекте "Semaphore" ... 7.5 Критическая секция и монитор ... 7.6 Механизм синхронизации "много читателей и один писатель" (MREW) ... 8. Обработка исключений в дополнительных потоках ... ... |
|||
:
Нравится:
Не нравится:
|
|||
05.01.2021, 14:25 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Добавлен пример использования TThreadedQueue https://github.com/loginov-dmitry/multithread/tree/master/ExQueue/ExThreadedQueue Комментарии есть в исходниках примера. В статье пока нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.01.2021, 21:18 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer, а можете добавить примеров с описанием где и как можно применять CreateThread. Например как решение в топике: https://stackoverflow.com/questions/25949391/simple-tcp-connect-timeout-wrapper-in-delphi Либо можно сделать что-то аналогичное с помощью TThread? ... |
|||
:
Нравится:
Не нравится:
|
|||
04.03.2021, 09:51 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Добавлены новые разделы: 9. Передача данных в дополнительный поток ... 9.1 Использование обычного списка (TList, TStringList, TThreadList) и периодический контроль списка ... 9.2 Использование обычного списка (TList, TStringList, TThreadList) и объекта Event ... 9.3 Использование очереди TThreadedQueue<T> (множество producer-потоков и один consumer-поток) ... 12. Работа с базой данных из дополнительного потока ... 13. Проблемы, возникающие при создании большого количество потоков ... В частности, содержимое п. 13: 1. Ограниченность адресного пространства. Сейчас практически никто не использует 32-разрядную ОС Windows. Если мы скомпилируем своё приложение в 32-битном режиме (с размером стека по умолчанию 1 МБ), запустим его в 64-битной ОС Windows и попытаемся создать 2000 потоков, то получим ошибку. Система не в состоянии создать более 1650 потоков. На каждый созданный поток Windows выделяет 1 МБ виртуальной памяти для 32-битного стека и 256 КБ виртуальной памяти для 64-битного стека (его Windows создаёт и поддерживает автоматически для обеспечения возможности работы 32-битных программ в 64-битной ОС). Насколько я понимаю, на размер 64-битного стека мы влиять не можем, но, если уменьшим размер виртуальной памяти под 32-битный стек (это можно сделать в окне Project / Options / Linker / Max stack size), то можем значительно увеличить максимальное количество потоков в приложении. При этом необходимо воздержаться от объявления локальных статических массивов с большим числом элементов. Данная проблема (с ограниченностью адресного пространства) актуальна только для 32-битных приложений. Если вы компилируете 64-битное приложение, то данной проблемы не существует. 2. Ограниченность физической памяти. Информация актуальна для 64-битной Windows и стандартного менеджера памяти (либо FastMM4). Один поток в 32-битной программе занимаем минимум 88 КБ ОЗУ. В 64-битной программе поток весит меньше - минимум 52 КБ ОЗУ (очевидно, экономия достигается за счёт того, что используется только один стек - 64-битный). Это значение не зависит от объёма виртуальной памяти, выделенной под стек. Учитывайте это, если планируете создавать огромное количество потоков! 3. Использование функции WinAPI-функции Sleep либо WaitForXXX для организации задержек в бесконечном цикле. Очень простое решение - реализовать в дополнительном потоке бесконечный цикл, периодически проверять значение какого-то флага (либо элемента в очереди), в зависимости от значения флага выполнять какое-либо действие, после чего переводить поток в спящий режим с помощью Sleep либо WaitForXXX. Если вы укажете время ожидания 1000 мс (или больше), то нет проблем (в том смысле, что нагрузка на процессор будет минимальной - примерно 50000 тактов в секунду при паузе в 1 секунду). Однако если Вы будете проверять значение флага каждые 10 миллисекунд, то нагрузка на процессор будет уже существенной - 2500000 тактов в секунду будет тратиться только на работу Sleep(10). Если у вас запущено 1000 таких потоков и каждый расходует 2500000 тактов в секунду, то будет обеспечена 100% загрузка одного ядра процессора (либо эта загрузка будет размазана по нескольким ядрам). Т.е. ваши 1000 потоков ещё не делают ничего полезного, но уже грузят процессор по полной программе! :) Для того, чтобы такой проблемы не было, не рекомендуется использовать Sleep либо WaitForXXX с маленькой задержкой. Гораздо лучше использовать WaitForXXX с большой задержкой (в том числе, INFINITY), а при изменении значения флага следует переводить объект ядра, который ожидает функция WaitForXXX, в сигнальное состояние. В этом случае потоки не будут тратить на контроль состояния флага практически никаких ресурсов процессора! 4. Использование TIdTCPServer для поддержания большого количества сетевых подключений. В древних версиях Indy10 вызовы Socket.ReadXXX приводили к высокой загрузке процессора. Приходилось их "разбавлять" с помощью Sleep(1) для снижения нагрузки на процессор. Такая же ситуация была с методом Socket.CheckForDataOnSource. Более того, раньше метод Socket.CheckForDataOnSource ещё и глючил - не возвращал управление, пока не закончится время ожидания, даже если пришли данные (поэтому приходилось его вызывать с минимальным таймаутом). Указанные проблемы приводили к созданию огромной нагрузке на процессор при большом количестве сетевых подключений. На данный момент в Indy10 эти проблемы решены. Актуальную версию Indy10 можно скачать с github, при этом она обычно работает c любой версией Delphi. Теперь методы ReadXXX и CheckForDataOnSource не создают никакой нагрузки на процессор и возвращают управление немедленно при появлении данных в сокете (в течение 100 микросекунд, если сервер и клиент запущены на одном компьютере). ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2021, 10:06 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
К слову. Не нашел ни одного упоминания OnTerminate в коде. Хотя он бывает полезен для некоторых случаев. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2021, 10:52 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
makhaon К слову. Не нашел ни одного упоминания OnTerminate в коде. Хотя он бывает полезен для некоторых случаев. Я его не использовал, поэтому не стал про него ничего сочинять. Нужны какие-то удачные примеры использования. Технически это тот же Synchronize, только метод подсовывается снаружи, т.е. поток не привязан к какой-то конкретной форме. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2021, 11:20 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Скорректирована информация по использованию TIdTCPServer ( ссылка ) Теперь информация изложена в следующем виде: 4. Неправильное использование компонента `TIdTCPServer`. При разработке TCP-серверов Delphi-программисты чаще всего используют компонент TIdTCPServer. При правильном использовании данный компонент может держать до 50000 подключений (существуют реальные примеры с таким количеством подключений). Разумеется, для этого программа должна быть 64-битной. Для поддержки 50000 подключений будет создано 50000 потоков и выделено около 3 ГБ ОЗУ, что весьма затратно. При таком количестве потоков ни в коем случае не должно быть циклов, в которых выполняется проверка чего-либо каждые 10 мс. Значение `Socket.ReadTimeout` должно быть не менее 10000 (10 секунд). При использовании `Socket.CheckForDataOnSource` для ожидания приёма данных от клиента также желательно использовать значение не менее 10000. **Внимание!** Перед каждым вызовом `Socket.CheckForDataOnSource` необходима проверка `if Socket.InputBuffer.Size = 0 then`, что обусловлено особенностями реализации метода `CheckForDataOnSource`. Если в буфере есть данные, то выполнять вызов `Socket.CheckForDataOnSource` не следует! **Информация!** Сами по себе данные в буфере `Socket.InputBuffer` появиться не могут. Появляются они там в следующих случаях: а) в контексте вызова метода `Socket.ReadXXX`, б) в контексте вызова метода `Socket.CheckForDataOnSource`, в) в момент подключения клиента к серверу, если клиент сразу же передал данные на сервер. **Информация!** На практике Delphi-программисту очень редко приходится разрабатывать TCP-сервер, способный держать 50000 соединений. Всё зависит от того, что именно делает TCP-сервер. Если он не выполняет какой-то особой обработки, а просто возвращает в ответ на запрос клиента текущее время (или иную информацию, которую не нужно запрашивать из базы данных или получать в результате сложных вычислений), то проблем никаких нет. Однако, если на каждый запрос приходится выполнять обращение к базе данных или производить сложные вычисления, то ресурсы сервера могут закончиться гораздо раньше (например, на 1000 соединений). В связи с этим рекомендую минимизировать количество обращений к базе данных и стараться держать всю необходимую информацию в памяти TCP-сервера, периодически обновляя её в фоновом потоке. **Внимание!** Не рекомендую использовать `TIdTCPServer` для решения задачи транзита данных. Данная задача отличается тем, что TCP-сервер не выполняет практически никакой обработки данных, а лишь передаёт клиенту "Б" данные, принятые от клиента "А" (и обратно). Если таких клиентов ("А" и "Б") будет 50000, то программа будет использовать около 3 ГБ ОЗУ. Загрузка процессора при активном обмене данными между клиентами будет также весьма приличной, поскольку при большом количестве потоков будет происходить очень много переключений контекста, а каждое переключение мы оцениваем в 50000 тактов. Существуют гораздо более удачные варианты решения задачи транзита данных: асинхронные сокеты и порты завершения ввода/вывода. И в том и в другом способе используется фиксированное количество потоков (например, 8 потоков для 4-ядерного процессора) и требуется намного меньше ОЗУ (как минимум, в 10 раз меньше, чем при использовании `TIdTCPServer`). Количество переключений контекста также намного меньше (сравнение имеет смысл производить только при высокой интенсивности обмена данными), т.к. за один квант времени поток сможет обработать данные, принятые от нескольких клиентов и передать данные нескольким клиентам. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.06.2021, 19:45 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
автор т.к. за один квант времени поток сможет обработать данные, принятые от нескольких клиентов и передать данные нескольким клиентам. лучше: так как в одном потоке могут быть обработаны сразу множество соединений и нет необходимости переключать контекст. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2021, 10:56 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
makhaon автор т.к. за один квант времени поток сможет обработать данные, принятые от нескольких клиентов и передать данные нескольким клиентам. лучше: так как в одном потоке могут быть обработаны сразу множество соединений и нет необходимости переключать контекст. Хорошо, я поправлю. На самом деле я этот момент я не проверял. Рассчитываю на то, что если я ошибаюсь (ну может для асинхронных сокетов каждое событие генерирует переключение контекста), то знающие люди меня поправят :) Но надеюсь, что работает так, как я думаю (в том числе для портов завершения ввода-вывода). ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2021, 23:06 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Автору большой респект за огромный труд и низкий поклон от меня! Это не руководство для начинающих программистов, а скорее руководство для любых программистов, которые начинают писать многопоточные приложения на Delphi. Такую тему надо закреплять в шапке форума. Например, очень удобно сделано на форуме 4PDA, там весь важный материал в шапке на первой же странице. P.S. Зашел на ваш Github и с удивлением выяснил, что оказывается я давно уже использую ваш модуль LDSLogger. Спасибо большое за вашу библиотеку, работает безотказно, несмотря сильное развитие возможностей языка Delphi в последних версиях Embarcadero Delphi. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.06.2021, 13:27 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Benten, спасибо за столь высокую оценку моих трудов. Добавлен новый раздел : Выполнение длительной операции в дополнительном потоке с отображением информационного модального окна, блокирующего работу пользователя с программой. Ссылка на пример пример (проверял в D2007 и 10.4) Вводная часть: При разработке приложения очень часто, в ответ на действия пользователя, приходится запускать на выполнение код, длительность которого может составить несколько секунд, при этом должен устанавливаться запрет на дальнейшие действия пользователя с программой, до тех пор, пока длительный код не завершит свою работу. С такими ситуациями мы встречаемся очень часто, например: при нажатии кнопки выполняем запрос к базе данных, а затем показываем пользователю результат запроса в новом окне; выполняем операцию с банковской картой; выполняем пробитие чека на кассе; выполняем формирование отчёта; отображаем на экране окно, которое в событии FormCreate выполняет длительную загрузку данных (из файла или из базы данных); сохраняем изменения, внесённые в документ; и т.д. Во всех случаях пользователю необходимо дождаться, пока операция не будет завершена. Пока операция выполняется, использование программы является бессмысленным. Более того, если мы возьмём, и просто запустим выполнение длительной операции в дополнительном потоке, не блокируя интерфейс пользователя, то пользователь может нажать что-нибудь лишнее, в результате чего программа может перейти в непредсказуемое состояние. При таком способе запуска длительной операции, для блокировки интерфейса пользователя рекомендуется выставить свойство Enabled := False для всех элементов, с которыми пользователь может взаимодействовать с помощью мыши либо клавиатуры, а также запретить закрытие окна (с помощью параметра CanClose в обработчике FormCloseQuery). Конечно, вы можете запустить длительный код в контексте основного потока. При этом пользователь не сможет ничего лишнего нажать до завершения операции (не забудьте изменить текст нажатой кнопки и курсор мыши на время выполнения операции - так пользователь будет хотябы понимать, что программа отреагировала на его действие и чем-то занимается). Если операция выполняется несколько секунд без какого-либо информирования пользователя, то пользоваться такой программой будет неприятно. Ещё хуже, если Windows повесит собственное окно с надписью "не отвечает" - в этом случае у пользователя может сложиться впечатление, что программа зависла. Если программа находится в таком состоянии более 30 секунд, то с большой вероятностью пользователь может попытаться решить "проблему" кардинально с помощью диспетчера задач либо путём перезагрузки компьютера. Вы можете перед началом длительной операции отобразить на экране дополнительное окно к надписью "Выполняется операция ХХХ. Ждите!", а в конце операции закрыть его (см п. 1.2). Однако при таком способе есть несколько минусов: Невозможно отобразить прошедшее время выполнения операции; Windows может навесить собственное окно с надписью "Не отвечает", после чего возможна проблема с "вылетом" текущего окна на задний план (в этом случае пользователь не сможет ничего нажать в окне, которое находится на переднем плане и может принять кардинальное решение о перезагрузке компьютера); В программе не работают никакие автоматические операции, запускающиеся из основного потока (обработчик TTimer.OnTimer не будет вызываться, пока основной поток не освободится); Основной поток не обрабатывает вызовы SendMessage, PostMessage, Synchronize, Queue; Если в программе используются асинхронные сетевые компоненты, использующие основной поток (например, Overbyte ICS), то их работа будет приостановлена, а соединения могут быть разорваны; Сложно организовать информирование пользователя о текущем состоянии выполняемой операции; Невозможно прервать ход выполнения длительной операции, даже если прерывание операции логично и не приводит к каким-либо проблемам (например, при формировании отчёта). Далее демонстрируется пример, в котором все перечисленные проблемы решены! По сути, это готовое решение, котором можно использовать практически в любом VCL-проекте. Но мне хотелось бы, чтобы читатель досконально разобрался с исходными кодами. Мною было потрачено на этот пример много дней и весь код я постарался привести в максимально читабельный вид. Также мною разработан модуль ParamsUtils.pas, который значительно упрощает передачу именованного списка параметров различного типа, что весьма полезно в ситуации, когда мы не можем напрямую вызвать целевую функцию с её "родными" параметрами. В папке ExWaitWindow находится пример, в котором демонстрируется способ отображения дополнительного модального окна при запуске длительной операции с помощью функции DoOperationInThread. Ниже пример использования функции DoOperationInThread: procedure TMainForm.Button3Click(Sender: TObject); begin DoOperationInThread(Self, OPERATION_TYPE_NONE, 'Длительные вычисления', TParamsRec.Build(['Min', 300, 'Max', 700]), ProgressOperation, NEED_SHOW_STOP_BTN); end; В данном примере на экране отображается модальное окно с надписью "Длительные вычисления". Данное окно отображается на экране около 5 секунд. В этом окне отображаются следующие элементы: Время, прошедшее от начала операции; Полоса ProgressBar, которая индицирует ход вычислений; Текущее значение, используемое в вычислительном алгоритме; Границы вычисления Min и Max; Кнопка "Отмена", позволяющая досрочно прервать выполнение операции. ⚠️ Внимание! Обратите внимание, что длительная операция запускается в дополнительном потоке! ... |
|||
:
Нравится:
Не нравится:
|
|||
09.07.2021, 14:58 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Добавлен новый раздел : Выполнение длительной операции в дополнительном потоке с отображением информационного модального окна, блокирующего работу пользователя с программой. Респект! Полезная фича, действительно. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.07.2021, 17:25 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Добавлен новый раздел : Выполнение длительной операции в дополнительном потоке с отображением информационного модального окна, блокирующего работу пользователя с программой. Хм, и VCL не штырит от такого? ... |
|||
:
Нравится:
Не нравится:
|
|||
09.07.2021, 17:55 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Fr0sT-Brutal, Ни разу не жаловалась :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.07.2021, 19:22 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
У тебя же все равно в итоге форма в доп. треде. Надежней делать на чистом winapi ... |
|||
:
Нравится:
Не нравится:
|
|||
12.07.2021, 10:18 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
DmSer Добавлен новый раздел: Выполнение длительной операции в дополнительном потоке с отображением информационного модального окна, блокирующего работу пользователя с программой. Если честно не понял, для чего используется событие. Давно не писал потоки, но по памяти. Создаем suspend поток и при отображении формы, в OnShow, стартуем его. Как по мне есть вероятность на быстрой операции получить бесконечное ожидание, так как поток войдет в ожидание до отображения формы. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2021, 13:29 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
jonik DmSer Добавлен новый раздел: Выполнение длительной операции в дополнительном потоке с отображением информационного модального окна, блокирующего работу пользователя с программой. Если честно не понял, для чего используется событие. Давно не писал потоки, но по памяти. Создаем suspend поток и при отображении формы, в OnShow, стартуем его. Как по мне есть вероятность на быстрой операции получить бесконечное ожидание, так как поток войдет в ожидание до отображения формы. Форма гарантированно отображается на экране. А закрывается только в одном месте - по команде из потока, после выполнения FEvent.WaitFor(INFINITE). Поэтому бесконечного ожидания не будет. Существует бесконечное множество способов решить одну и ту же задачу. С эвентом - лишь один из способов. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2021, 18:59 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
У меня форма зависает. D10.3.3 и D10.4.2 Один или два раза отрабатывает норм, мелькает и закрывается. А в основном зависает. Если поставить задержку, то отрабатывает норм. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.11.2021, 01:03 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
jonik У меня форма зависает. D10.3.3 и D10.4.2 Один или два раза отрабатывает норм, мелькает и закрывается. А в основном зависает. Если поставить задержку, то отрабатывает норм. Что зависает? Мой пример? ... |
|||
:
Нравится:
Не нравится:
|
|||
13.11.2021, 15:31 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
Да, ваш пример, где быстрая операция. При чем зависает чаще, чем не зависает. Один раз запускаю - мелькнуло, отработало. Запускаю сразу же ещё раз - зависает :) Ну и так периодически. То есть как по мне код для быстрых операций не рабочий. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.11.2021, 10:36 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
jonik То есть как по мне код для быстрых операций не рабочий. Что там за код, который "зависает"? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.11.2021, 10:46 |
|
Многопоточное программирование в Delphi для начинающих
|
|||
---|---|---|---|
#18+
jonik Да, ваш пример, где быстрая операция. При чем зависает чаще, чем не зависает. Один раз запускаю - мелькнуло, отработало. Запускаю сразу же ещё раз - зависает :) Ну и так периодически. То есть как по мне код для быстрых операций не рабочий. Пример с гитхаба не зависает. Предполагаю, что вы скачали пример из гитхаба, что-то в нем подкрутили (может эвент удалили, я не знаю), после этого у вас стало зависать. Попробуйте ещё раз скачать проект из гитхаба, в отдельную папку. Оттуда скомпилировать и запустить. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2021, 09:39 |
|
|
start [/forum/topic.php?all=1&fid=58&tid=2036872]: |
0ms |
get settings: |
16ms |
get forum list: |
6ms |
check forum access: |
1ms |
check topic access: |
1ms |
track hit: |
53ms |
get topic data: |
3ms |
get forum data: |
1ms |
get page messages: |
2725ms |
get tp. blocked users: |
0ms |
others: | 2450ms |
total: | 5256ms |
0 / 0 |