|
Многопоточное программирование в 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 |
|
|
start [/forum/topic.php?fid=58&msg=39986306&tid=2036872]: |
0ms |
get settings: |
28ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
56ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
537ms |
get tp. blocked users: |
2ms |
others: | 2569ms |
total: | 3224ms |
0 / 0 |