Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Delphi |
![]() ![]() |
Топик располагается на нескольких страницах: 1 2 3 [все] |
garun Member Откуда: Оттуда Сообщений: 289 |
Есть процедура, которая работает с VCL. К этой процедуре обращается несколько потоков. Вопрос такой, нужно обязательно заключать в TThread.Synchronize() вызов самой процедуры внутри потоков или же можно заключить в TThread.Synchronize() только нужный участок кода в уже вызываемой процедуре? То есть будет ли правильно работать такой код:procedure JobVCL; begin TThread.Synchronize(nil, procedure begin // тут код работы с VCL end); end; TThread.CreateAnonymousThread(procedure begin ... JobVCL; ... end).Start; |
17 фев 21, 12:20 [22282148] Ответить | Цитировать Сообщить модератору |
Fr0sT-Brutal Member Откуда: Сообщений: 587 |
Как удобней, так и делай. Принципиальной разницы нет |
17 фев 21, 13:03 [22282202] Ответить | Цитировать Сообщить модератору |
YuRock Member Откуда: Донецк Сообщений: 4402 |
garun, Лучше вообще без синхронайз логику построить. Пусть поток независимо занимается работой, можно обновлять какие-то общие данные-результаты для отображения. А морда независимо что-то показывает. Иногда что-то берет из общих данных-результатов. |
17 фев 21, 13:04 [22282207] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
Лучше по таймеру в основном потоке проверять результаты расчетов и выводить что нужно. |
||||
17 фев 21, 13:05 [22282208] Ответить | Цитировать Сообщить модератору |
Fr0sT-Brutal Member Откуда: Сообщений: 587 |
+ Слать из рабочих потоков форме сообщения и забыть про синхронайз |
||||
17 фев 21, 13:06 [22282210] Ответить | Цитировать Сообщить модератору |
Zelius Member Откуда: Россия, Москва Сообщений: 1522 |
garun, по твоему коду правильнее так procedure JobVCL; begin // тут код работы с VCL end; TThread.CreateAnonymousThread(procedure begin ... TThread.Synchronize(JobVCL); ... end).Start; |
17 фев 21, 13:07 [22282214] Ответить | Цитировать Сообщить модератору |
garun Member Откуда: Оттуда Сообщений: 289 |
Zelius, "Правильнее" почему? Чем отличается работа моего кода от вашего? |
17 фев 21, 14:07 [22282280] Ответить | Цитировать Сообщить модератору |
ъъъъъ Member Откуда: Сообщений: 1769 |
...только треды начинают работать по очереди. |
||||
17 фев 21, 14:13 [22282285] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
ъъъъъ, Это однопоточная многопоточность. |
17 фев 21, 14:15 [22282287] Ответить | Цитировать Сообщить модератору |
ъъъъъ Member Откуда: Сообщений: 1769 |
Корпоративная. |
||||
17 фев 21, 14:29 [22282296] Ответить | Цитировать Сообщить модератору |
Zelius Member Откуда: Россия, Москва Сообщений: 1522 |
по хелпу, отличается одним вызовом и личными предпочтениями ) а так по сути тоже самое |
||||
17 фев 21, 16:13 [22282358] Ответить | Цитировать Сообщить модератору |
Fr0sT-Brutal Member Откуда: Сообщений: 587 |
У него Job в середине цикла вызывается, судя по "..." перед и после, значит, здесь все нормально |
||||||||
17 фев 21, 16:51 [22282367] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
Сообщение было отредактировано: 17 фев 21, 16:55 |
||||
17 фев 21, 17:01 [22282371] Ответить | Цитировать Сообщить модератору |
alekcvp Member Откуда: Сообщений: 2730 |
|
||||
18 фев 21, 12:22 [22282701] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
alekcvp, А теперь представь что это Queue вызывается допустим N раз в секунду, а юзер открыл какой-то диалог и ушел. Вопрос 1: Что будет, если юзер закроет диалог весьма не скоро, а в очереди накопится огромное кол-во вызовов синхронизированной процедуры? Вопрос 2: Через сколько времени в ОС кончатся ресурсы и все упадет, если юзер так и не закроет диалог? Сообщение было отредактировано: 18 фев 21, 13:13 |
18 фев 21, 13:18 [22282758] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12572 |
Модальное окно не блокирует обработку Queue/Synchoronize |
||||
18 фев 21, 13:45 [22282784] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
Но тогда выбери сам любую другую причину длительной занятости главного потока. |
||||
18 фев 21, 14:10 [22282808] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12572 |
|
||||
18 фев 21, 14:25 [22282823] Ответить | Цитировать Сообщить модератору |
YuRock Member Откуда: Донецк Сообщений: 4402 |
|
||||||||
18 фев 21, 14:26 [22282825] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12572 |
|
||||
18 фев 21, 14:33 [22282833] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
_Vasilisk_, Если инициатор обновлений гуя сам главный поток, а результаты расчета другие потоки обновляют в промежуточном контейнере (в куче) - то не будет. Сообщение было отредактировано: 18 фев 21, 14:44 |
18 фев 21, 14:47 [22282848] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12572 |
Я знаю решение: в главном потоке вместо GetMessage использовать MsgWaitForMultipleObjects, а из вычислителя дергать SetEvent. Но в VCL такое не прикрутишь |
||||
18 фев 21, 15:00 [22282870] Ответить | Цитировать Сообщить модератору |
alekcvp Member Откуда: Сообщений: 2730 |
Сообщение было отредактировано: 18 фев 21, 14:54 |
||||
18 фев 21, 15:00 [22282871] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
_Vasilisk_, Да. По таймеру в процессе расчетов. Имхо так надежней и безопасней чем через sendmessage. Ну и это кроссплатформенно, как бонус. Сообщение было отредактировано: 18 фев 21, 14:56 |
18 фев 21, 15:01 [22282872] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12572 |
|
||||
18 фев 21, 15:04 [22282879] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
_Vasilisk_, Но не sendmessage. |
18 фев 21, 15:10 [22282889] Ответить | Цитировать Сообщить модератору |
YuRock Member Откуда: Донецк Сообщений: 4402 |
Первая процедура, вызванная в synchronize, еще не завершилась, а уже запустилась другая. Это грозит крахом логики. Впрочем, с обычными сообщениями - те же проблемы возможны. Я просто думал, что там реальная очередь выполнений. |
||||||||
18 фев 21, 15:45 [22282921] Ответить | Цитировать Сообщить модератору |
Dimitry Sibiryakov Member Откуда: Сообщений: 52445 |
А ты всерьёз полагал, что Synchronize в двух разных потоках обязаны синхронизироваться не только с главным потоком, но и между собой? Да, это полный крах логики. Posted via ActualForum NNTP Server 1.5 |
||
18 фев 21, 15:47 [22282923] Ответить | Цитировать Сообщить модератору |
Fr0sT-Brutal Member Откуда: Сообщений: 587 |
А ничего на самом деле. Окно висит, сообщения обрабатываются |
||||
18 фев 21, 15:49 [22282924] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12572 |
rgreat, Если бы у меня зависал главный поток, то я бы делал синхронизацию через промежуточный поток procedure TCalcThread.Execute; begin ...... SetEvent(NotifyEvent); .... end; procedure TNotifyThread.Execute; begin while not Terminated do begin WaitForSingleObject(NotifyEvent); Synchronize(UpdateVCL) end; end;Хотя на реальном проекте у меня сделано так
|
|
18 фев 21, 15:52 [22282929] Ответить | Цитировать Сообщить модератору |
YuRock Member Откуда: Донецк Сообщений: 4402 |
Но была мысль, да. |
||||||
18 фев 21, 16:12 [22282943] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
_Vasilisk_, И зачем так все усложнять... |
18 фев 21, 16:35 [22282954] Ответить | Цитировать Сообщить модератору |
alekcvp Member Откуда: Сообщений: 2730 |
А как они могут выполняться параллельно в одном потоке? Квантовая однопоточность что-ли? Типа выполняется один поток, но неизвестно какой? 😁 Разумеется, при условии что первый Synchronize не вызывает ProcessMessages(). Сообщение было отредактировано: 18 фев 21, 17:08 |
||||||
18 фев 21, 17:14 [22282988] Ответить | Цитировать Сообщить модератору |
Dimitry Sibiryakov Member Откуда: Сообщений: 52445 |
Рекурсивно. Posted via ActualForum NNTP Server 1.5 |
||
18 фев 21, 17:43 [22283003] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12572 |
|
||||||||
18 фев 21, 18:18 [22283028] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
Я бы сказал что твой вариант мне кажется более костыльным. Да и без таймера в обработке GUI на длительных задачах чаще всего все равно не обойтись. По таймеру можно делать плавную анимацию прогресса даже если сами итерации в расчетном потоке редки или неравномерны. |
||||
18 фев 21, 18:30 [22283038] Ответить | Цитировать Сообщить модератору |
white_nigger Member Откуда: Тула Сообщений: 2469 |
|
||||
19 фев 21, 02:11 [22283220] Ответить | Цитировать Сообщить модератору |
kealon(Ruslan) Member Откуда: Нижневартовск Сообщений: 6255 |
GUI должен заниматься GUI, расчётчик должен расчитывать - как ни парадоксально звучит |
||||||||
19 фев 21, 08:28 [22283242] Ответить | Цитировать Сообщить модератору |
white_nigger Member Откуда: Тула Сообщений: 2469 |
|
||||
19 фев 21, 16:06 [22283568] Ответить | Цитировать Сообщить модератору |
Dimitry Sibiryakov Member Откуда: Сообщений: 52445 |
Отображать прогресс на каждую итерацию цикла - самый надёжный способ получить невыносимые тормоза. Posted via ActualForum NNTP Server 1.5 |
||
19 фев 21, 16:13 [22283574] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
Поток должен складывать результат своей работы в специальный контейнер в который есть доступ у GUI потока. В таком случае потоки работают независимо друг от друга и друг другу не мешают. |
||||
19 фев 21, 16:42 [22283597] Ответить | Цитировать Сообщить модератору |
makhaon Member Откуда: A galaxy far far away Сообщений: 3788 |
rgreat, поддерживаю. потоку входные данные где-то отдали и оставили его в покое. поток считает. если есть необходимость продвигает прогресс через какой-то синхронный код (лучше, конечно, не за одну итерацию, но тут всяко бывает. бывает что итерации долгие) когда досчитал результат, сложил куда-то в переменную и сказал гую что готово. всё. |
19 фев 21, 19:15 [22283718] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
А я обычно использую контейнер с доступом к нему через обычную TCriticalSection. При этом более важный поток заходит туда через .Enter a менее важный через TryEnter. |
||||
19 фев 21, 19:23 [22283723] Ответить | Цитировать Сообщить модератору |
_Vasilisk_ Member Откуда: Украина, Харьков Сообщений: 12572 |
|
|||||||||||||||||||||||||||||||||||
19 фев 21, 20:17 [22283759] Ответить | Цитировать Сообщить модератору |
white_nigger Member Откуда: Тула Сообщений: 2469 |
|
||||
19 фев 21, 20:34 [22283769] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
_Vasilisk_, Что у тебя в таблице за цифры? Не понятно что не так. Чего страшного от того что забор данных может изредка совпасть с сохранением результата расчета? Либо GUI тред в этот раз не отработает, либо Calc тред совсем немного подождет. Сообщение было отредактировано: 19 фев 21, 23:21 |
19 фев 21, 23:19 [22283840] Ответить | Цитировать Сообщить модератору |
YuRock Member Откуда: Донецк Сообщений: 4402 |
|
||||
20 фев 21, 02:26 [22283868] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
YuRock, Вообще, в нормально написанном ПО время сохранения данных в "экспортный" контейнер должно составлять исчезающе малую честь времени в сравнении с периодом цикла таймера GUI и цикла таймера Calc потока. Так что вероятность постоянного пропуска цикла должна быть порядка уровня шанса внезапного взрыва сверхновой на солнце. Если боязно можно обойтись и без TryEnter, но тогда стоит написать код так что бы запись и чтение из контейнера занимали около нуля микросекунд. Т.е. Lock, Assign, Unlock. Ну или вообще TInterlocked.Exchange без всяких критических секций. Сообщение было отредактировано: 20 фев 21, 03:22 |
20 фев 21, 03:19 [22283875] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
Ну и собственно если GUI поток обновляет данные раз в секунду а Calc поток раз в минуту то максимально теоретически возможно пропустить только одно из 60 обновлений GUI. |
20 фев 21, 03:33 [22283876] Ответить | Цитировать Сообщить модератору |
YuRock Member Откуда: Донецк Сообщений: 4402 |
Один поток пишет иногда какую-нибудь сотню байт, gui - читает эти байты раз в секунду. Даже если произойдет блокировка - она продлится в районе 0-16 мс. В любом случае времени это займет столько. Нисколько, короче. При этом будет гарантия обновления экрана. |
||||
20 фев 21, 03:55 [22283878] Ответить | Цитировать Сообщить модератору |
rgreat Member Откуда: Сообщений: 6563 |
YuRock, Честно сказать я сам себя запутал, ибо TryEnter предполагался на случай ленивого варианта когда передаточного контейнера вообще нет и расчетный поток постоянно работает в фоне с редкими включениями на перерасчет, а GUI поток читает результат прямо из переменных расчетного потока. |
20 фев 21, 04:11 [22283879] Ответить | Цитировать Сообщить модератору |
Топик располагается на нескольких страницах: 1 2 3 [все] |
Все форумы / Delphi | ![]() |