powered by simpleCommunicator - 2.0.29     © 2024 Programmizd 02
Map
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Многопоточное программирование в Delphi для начинающих
25 сообщений из 160, страница 6 из 7
Многопоточное программирование в Delphi для начинающих
    #39995708
didgik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman
didgik
И что тогда использовать вместо Sleep?

Например в WaitFor*Object, у которого в аргументах событие, которому можно посигналить извне.


Не очень понятно извне это из основного потока? Повесить там таймер и раз, допустим, в 10 мин. посылать сигнал?
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #39995725
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
didgik
А я вот не понял п4.1
Зачем Sleep() обертывать в WaitTimeout ?


Можно и не обертывать. В данном случае поведение программы от этого не изменится. Однако действие по ожиданию таймаута может быть более сложным, чем просто вызвать Sleep. В этом случае разумнее вынести код в отдельную функцию. В дальнейшем можно улучшить код в данной функции, не переделывая все места, из которых эта функция вызывается.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #39995727
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
didgik

И что тогда использовать вместо Sleep?


В некоторых случаях можно использовать более навороченную версию: ThreadWaitTimeout из модуля MTUtils.pas.

Но в идеале следует использовать функцию WaitXXXXX
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #39995731
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
04.09.2020 16:59, DmSer пишет:
> Но в идеале следует использовать функцию WaitXXXXX

мотивируй
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #39995734
didgik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
didgik

И что тогда использовать вместо Sleep?


В некоторых случаях можно использовать более навороченную версию: ThreadWaitTimeout из модуля MTUtils.pas.

Но в идеале следует использовать функцию WaitXXXXX

я, кстати, не нашел ThreadWaitTimeout в 2007.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #39995745
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мимопроходящий

04.09.2020 16:59, DmSer пишет:
> Но в идеале следует использовать функцию WaitXXXXX

мотивируй


Оверхед меньше по сравнению с sleep(10) в цикле.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #39995753
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
didgik
DmSer
пропущено...


В некоторых случаях можно использовать более навороченную версию: ThreadWaitTimeout из модуля MTUtils.pas.

Но в идеале следует использовать функцию WaitXXXXX

я, кстати, не нашел ThreadWaitTimeout в 2007.


Там её нет. Искать нужно там же где статья.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #39995786
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
didgik
wadman
пропущено...

Например в WaitFor*Object, у которого в аргументах событие, которому можно посигналить извне.


Не очень понятно извне это из основного потока? Повесить там таймер и раз, допустим, в 10 мин. посылать сигнал?
Из любого потока.
Посылать сигнал только тогда, когда нужно. Будить таким образом поток, если нужно.
А в Thread.Destroy сделать Terminate и SetEvent. А в потоке после ожидания проверять на Terminated.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #39995965
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
Мимопроходящий

04.09.2020 16:59, DmSer пишет:
> Но в идеале следует использовать функцию WaitXXXXX

мотивируй


Оверхед меньше по сравнению с sleep(10) в цикле.


Помимо меньшего оверхеда также следует отметить время реакции.

Поток, остановленный по команде Sleep, может возобновить работу только после срабатывания системного таймера. А по умолчанию системный таймер срабатывает примерно раз в 16 миллисекунд.

При ожидании на WaitForXXXXX возобновление работы происходит намного оперативнее.

Идеальный случай, когда в момент вызова SetEvent / ReleaseMutex у планировщика есть возможность запустить ожидающий поток на том же ядре и отсутствуют другие желающие, кому требуется это же ядро. Тогда планировщик запускает ожидающий поток немедленно, не прибегая к системному таймеру или к механизму асинхронного вызова APC. На всё про всё уходит порядка 6 микросекунд (железо не самое мощное).
Однако такое происходит редко, чаще планировщик запускает ожидающий поток с использованием механизма APC (с программным прерыванием), в этом случае уходит от 20 до 50 микросекунд (на моих тестах).
Худший случай, когда механизм APC не смог запустить ожидаемый поток (мог вклиниться поток с более высоким приоритетом), тогда запуск ожидающего потока будет запланирован уже по событию системного таймера.
Как-то так оно работает (в моём понимании).
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40021250
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
За последнее время:
1. Добавлен раздел "1.2 Можно ли избежать многопоточного программирования", к нему пример ExNotUseThreads
2. Добавлен раздел "Основные объекты синхронизации в Windows"
3. Добавлен раздел "7.1 Главный поток управляет работой дополнительного потока с помощью объекта "Event" (событие)" и к нему пример FastStopThread
4. Добавлен пример SimpleLogger, который очень наглядно демонстрирует преимущество использования доп. потока при записи в лог-файл (соответствующее описание к данному примеру пока отсутствует).
5. Исправлено несколько замечаний, в том числе большая часть замечаний от _Vasilisk_
6. Учтены некоторые предложения
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40021565
Sapersky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DmSer
1. Добавлен раздел "1.2 Можно ли избежать многопоточного программирования", к нему пример ExNotUseThreads
Про псевдо-многопоточность я бы ещё написал, что можно прятать умеренные по времени задержки (до 0.5 с) в OnIdle. OnIdle срабатывает, когда нет новых сообщений окну, в частности когда пользователь перестаёт тыкать в клавиатуру/мышь. То есть можно отложить относительно длительные действия на периоды неактивности пользователя.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40023723
Volk65
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А я вот просто хочу выразить признательность автору статьи!
От "не новичка" в Delphi, но неработающего с потоками (пока). Периодически читаю что-то о потоках, т.к. сегодня не надо, а завтра... Такая статья очень поможет если вдруг "припрёт".
Прочитал весь топик. Начну читать статью... Еще раз - автору спасибо.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40023762
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Volk65
А я вот просто хочу выразить признательность автору статьи!
От "не новичка" в Delphi, но неработающего с потоками (пока). Периодически читаю что-то о потоках, т.к. сегодня не надо, а завтра... Такая статья очень поможет если вдруг "припрёт".
Прочитал весь топик. Начну читать статью... Еще раз - автору спасибо.
А классику "Multithreading – The Delphi Way" уже прочитал? )) Имхо лучшее для "не новичка"
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40033612
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Volk65
А я вот просто хочу выразить признательность автору статьи!
От "не новичка" в Delphi, но неработающего с потоками (пока). Периодически читаю что-то о потоках, т.к. сегодня не надо, а завтра... Такая статья очень поможет если вдруг "припрёт".
Прочитал весь топик. Начну читать статью... Еще раз - автору спасибо.


Спасибо, буду рад, если мои труды принесут для кого-то пользу!

Добавлены следующие новые разделы:

7.2 Использование объекта "Event" для разработки потока логгирования ...

7.3 Пара слов об объекте "Mutex" ...

7.4 Пара слов об объекте "Semaphore" ...

7.5 Критическая секция и монитор ...

7.6 Механизм синхронизации "много читателей и один писатель" (MREW) ...

8. Обработка исключений в дополнительных потоках ...
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40034473
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добавлен пример использования TThreadedQueue
https://github.com/loginov-dmitry/multithread/tree/master/ExQueue/ExThreadedQueue

Комментарии есть в исходниках примера. В статье пока нет.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40050547
destroyer86
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DmSer, а можете добавить примеров с описанием где и как можно применять CreateThread.
Например как решение в топике: https://stackoverflow.com/questions/25949391/simple-tcp-connect-timeout-wrapper-in-delphi
Либо можно сделать что-то аналогичное с помощью TThread?
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40059641
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добавлены новые разделы:

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 микросекунд, если сервер и клиент запущены на одном компьютере).
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40059667
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
К слову. Не нашел ни одного упоминания OnTerminate в коде. Хотя он бывает полезен для некоторых случаев.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40059688
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaon
К слову. Не нашел ни одного упоминания OnTerminate в коде. Хотя он бывает полезен для некоторых случаев.


Я его не использовал, поэтому не стал про него ничего сочинять. Нужны какие-то удачные примеры использования. Технически это тот же Synchronize, только метод подсовывается снаружи, т.е. поток не привязан к какой-то конкретной форме.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40075768
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Скорректирована информация по использованию 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`). Количество переключений контекста также намного меньше (сравнение имеет смысл производить только при высокой интенсивности обмена данными), т.к. за один квант времени поток сможет обработать данные, принятые от нескольких клиентов и передать данные нескольким клиентам.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40075821
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор т.к. за один квант времени поток сможет обработать данные, принятые от нескольких клиентов и передать данные нескольким клиентам.
лучше: так как в одном потоке могут быть обработаны сразу множество соединений и нет необходимости переключать контекст.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40075881
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaon
автор т.к. за один квант времени поток сможет обработать данные, принятые от нескольких клиентов и передать данные нескольким клиентам.

лучше: так как в одном потоке могут быть обработаны сразу множество соединений и нет необходимости переключать контекст.

Хорошо, я поправлю. На самом деле я этот момент я не проверял. Рассчитываю на то, что если я ошибаюсь (ну может для асинхронных сокетов каждое событие генерирует переключение контекста), то знающие люди меня поправят :)
Но надеюсь, что работает так, как я думаю (в том числе для портов завершения ввода-вывода).
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40076097
Benten
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Автору большой респект за огромный труд и низкий поклон от меня!

Это не руководство для начинающих программистов, а скорее руководство для любых программистов, которые начинают писать многопоточные приложения на Delphi.
Такую тему надо закреплять в шапке форума. Например, очень удобно сделано на форуме 4PDA, там весь важный материал в шапке на первой же странице.

P.S. Зашел на ваш Github и с удивлением выяснил, что оказывается я давно уже использую ваш модуль LDSLogger.
Спасибо большое за вашу библиотеку, работает безотказно, несмотря сильное развитие возможностей языка Delphi в последних версиях Embarcadero Delphi.
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40083038
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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;
Кнопка "Отмена", позволяющая досрочно прервать выполнение операции.
⚠️ Внимание! Обратите внимание, что длительная операция запускается в дополнительном потоке!
...
Рейтинг: 0 / 0
Многопоточное программирование в Delphi для начинающих
    #40083081
Softologic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DmSer

Добавлен новый раздел : Выполнение длительной операции в дополнительном потоке с отображением информационного модального окна, блокирующего работу пользователя с программой.

Респект! Полезная фича, действительно.
...
Рейтинг: 0 / 0
25 сообщений из 160, страница 6 из 7
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Многопоточное программирование в Delphi для начинающих
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]