Вверх ↑
Этот топик читают: Гость
Ответов: 704
Рейтинг: 7
#1: 2019-01-03 16:10:02 ЛС | профиль | цитата
Здравствуйте!
Считал что Synchronize ждет исполнения события а DeferredEvent не ждет. Но выходит они оба не ждут? Правда, видно что DeferredEvent меньше таки грузит свой поток, ибо поток быстрее соседнего считает и сообщения от DeferredEvent приходят реже чем от Synchronize.

Add(MainForm,2953706,21,105)
{
}
Add(Thread,12578108,455,126)
{
Delay=0
link(onExec,10598358:doEvent,[])
}
Add(Timer,16683636,574,126)
{
Interval=1
Enable=1
AutoStop=1
link(onTimer,6441049:doMessage,[])
}
Add(Button,5158431,371,126)
{
Left=15
Top=80
Width=130
Caption="Synchronize"
link(onClick,4437896:doEvent1,[])
}
Add(Message,6441049,623,126)
{
Message="Synch"
}
Add(Synchronize,11621601,532,126)
{
link(onSync,16683636:doTimer,[])
}
Add(Debug,10598358,504,126)
{
WEName="Synch"
link(onEvent,11621601:doSynchronize,[])
}
Add(Thread,9288934,455,182)
{
Delay=0
link(onExec,15871113:doEvent,[])
}
Add(Timer,15160710,574,182)
{
Interval=1
Enable=1
AutoStop=1
link(onTimer,13800275:doMessage,[])
}
Add(Message,13800275,623,182)
{
Message="Deferred"
}
Add(Debug,15871113,504,182)
{
WEName="Deferred"
link(onEvent,3240971:doDeferredEvent,[])
}
Add(DeferredEvent,3240971,532,182)
{
link(onDeferredEvent,15160710:doTimer,[])
}
Add(Hub,4437896,420,126)
{
link(onEvent1,12578108:doStart,[])
link(onEvent2,9288934:doStart,[(445,139)(445,188)])
}


Можно, кстати, их использовать взаимозаменяемо для организации некоторого накопительного стека от разных потоков в один интерфейсный элемент без всяких мьютексов?

Add(Thread,12578108,455,126)
{
Delay=0
link(onExec,10598358:doEvent,[])
}
Add(Timer,16683636,574,126)
{
Interval=1
Enable=1
AutoStop=1
link(onTimer,5915712:doData,[])
}
Add(Button,5158431,371,126)
{
Left=15
Top=80
Width=130
Caption="Synchronize"
link(onClick,4437896:doEvent1,[])
}
Add(Message,6441049,742,126)
{
}
Add(Synchronize,11621601,532,126)
{
link(onSync,16683636:doTimer,[])
}
Add(Debug,10598358,504,126)
{
WEName="Synch"
link(onEvent,11621601:doSynchronize,[])
}
Add(Thread,9288934,455,182)
{
Delay=0
link(onExec,15871113:doEvent,[])
}
Add(Timer,15160710,574,182)
{
Interval=1
Enable=1
AutoStop=1
link(onTimer,12013476:doData,[])
}
Add(Message,13800275,742,182)
{
Message="Deferred"
}
Add(Debug,15871113,504,182)
{
WEName="Deferred"
link(onEvent,3240971:doDeferredEvent,[])
}
Add(DeferredEvent,3240971,532,182)
{
link(onDeferredEvent,15160710:doTimer,[])
}
Add(Hub,4437896,420,126)
{
link(onEvent1,12578108:doStart,[])
link(onEvent2,9288934:doStart,[(445,139)(445,188)])
}
Add(HubEx,14560959,707,126)
{
link(onEvent,6441049:doMessage,[])
}
Add(DoData,12013476,630,182)
{
Data=String(Deferred)
link(onEventData,14560959:doWork3,[(711,188)])
}
Add(DoData,5915712,630,126)
{
Data=String(Synch)
link(onEventData,14560959:doWork2,[])
}


Редактировалось 1 раз(а), последний 2019-01-03 16:12:48
карма: 0

0
Ответов: 4628
Рейтинг: 749
#2: 2019-01-03 17:02:18 ЛС | профиль | цитата
Neo писал(а):
Считал что Synchronize ждет исполнения события а DeferredEvent не ждет.
Правильно считал. Только в первой схеме нечего ждать (нету продолжительных операций, все сообщения обрабатываются достаточно быстро). Непонятно что должен показать первый пример. Thread.FastStop=False - сознательно? Тогда зачем там таймеры (тем более, повторные вызовы doTimer ничего не делают)? По своей сути таймер - это ещё один источник сообщений в дополнение к тем двум компонентам: Synchronize - вызывает сообщение сразу и ждёт обработки, DeferredEvent - вызывает "когда-то потом", Timer - вызывает "когда-то потом примерно с указанной периодичностью".
Если таймер + MessageBox были призваны просто занять главный поток, чтобы проверить ждут ли его освобождения Synchronize/DeferredEvent, то, вероятно, MessageBox - неудачный способ задержки в данном случае, так как само окно MessageBox пропускает на обработку сообщения от Synchronize/DeferredEvent, потому что они ему неизвестны, а блокирует только оконные сообщения, не предназначенные ему (а то и вообще разрешает всё, кроме попыток активации других окон, чтобы самому быть наверху).
Neo писал(а):
и сообщения от DeferredEvent приходят реже чем от Synchronize
Вполне возможно что очередь сообщений переполняется и есть пропуск сообщений.

Редактировалось 4 раз(а), последний 2019-01-03 17:15:59
карма: 26

0
Ответов: 704
Рейтинг: 7
#3: 2019-01-03 17:28:17 ЛС | профиль | цитата
Netspirit писал(а):
Вполне возможно что очередь сообщений переполняется и есть пропуск сообщений.

DeferredEvent похоже имеет пропуск сообщений. А так же не транслирует временами через себя данные если накапливается очередь событий из 10. Странно что он не гарантирует целостность данных. - как поступать чтоб не терять данные? Организовывать стек в каждом случае?

С этим же сталкивался и в Вашем компоненте TCPServer по синхронизированной выдаче данных - некоторые теряются при очереди в десяток сообщений.
Пока организовал стек на эти события от TCPServer и читаю таймером на синхронизированную обработку. Рассчитывал заменить это на один из обсуждаемых компонентов.

Thread.FastStop=False - сознательно, но заменил таймеры на продолжительные операции и понял разницу.

Редактировалось 3 раз(а), последний 2019-01-03 17:31:52
карма: 0

0
Ответов: 4628
Рейтинг: 749
#4: 2019-01-03 17:31:28 ЛС | профиль | цитата
Neo писал(а):
Странно что он не гарантирует целостность данных.
Поскольку при вызове doDefferedEvent нету ожидания события, то последующие вызовы затирают данные, подготовленные для предыдущего вызова (компонент сохраняет первые данные у себя, а если событие не произошло до второго вызова, то вторые данные их затирают). Плюс ещё данные сохраняются одним потоком (вызвавшим doDefferedEvent), а считываются другим (главным потоком приложения) - при частых вызовах возможна порча данных, выдаваемых событием.
В общем, DeferredEvent не предназначено для синхронизации. Его задача - "развести" два действия "по фазе". В частном случае - уничтожить экземпляр мультиэлемента "из самого себя".

Редактировалось 3 раз(а), последний 2019-01-03 17:37:49
карма: 26

0
Ответов: 704
Рейтинг: 7
#5: 2019-01-03 17:37:10 ЛС | профиль | цитата
Netspirit писал(а):
компонент сохраняет первые данные у себя, а если событие не произошло до второго вызова, то вторые данные их затирают

То есть его нельзя применить для вывода в оконные элементы если периодически бывает нагрузка высокой интенсивности, а после простой параллельного потока? Как тогда поступать надежнее в "час пик"?

Редактировалось 2 раз(а), последний 2019-01-03 17:39:17
карма: 0

0
Ответов: 4628
Рейтинг: 749
#6: 2019-01-03 17:40:45 ЛС | профиль | цитата
Нет. "Не предназначен для синхронизации". В таких случаях параллельный поток данные пишет, например, в Memory (кажется, на строках могут быть проблемы), а обычный таймер периодически их считывает и выводит пользователю. Или то же самое, но запись/чтение данных защищены SafeMode - наиболее корректный способ (в т.ч. для строк). Или есть ещё вариант "делителя" - с помощью Synchronize показывать пользователю данные не непрерывно, блокируя главный поток, а периодически с помощью CounterEx, скажем, каждое 100-е событие выводить пользователю.

Редактировалось 4 раз(а), последний 2019-01-03 17:52:56
карма: 26

0
Ответов: 704
Рейтинг: 7
#7: 2019-01-03 17:46:43 ЛС | профиль | цитата
Netspirit, благодарю! Буду закреплять понятое на деле.

--- Добавлено в 2019-01-03 17:58:17

Netspirit писал(а):
с помощью Synchronize показывать пользователю данные не непрерывно, блокируя главный поток, а периодически с помощью CounterEx, скажем, каждое 100-е событие выводить пользователю.

Хорошая идея! Тогда стоит добавить счет нагрузки событий/секунду и применять разные алгоритмы вывода/обработки во время простоя и во время более интенсивной работы.

Редактировалось 2 раз(а), последний 2019-01-03 17:59:01
карма: 0

0
Ответов: 704
Рейтинг: 7
#8: 2019-01-03 19:38:50 ЛС | профиль | цитата
А нет ли способа узнать в отладчике откуда пришли данные: из главного потока или из параллельного?
карма: 0

0
8
Сообщение
...
Прикрепленные файлы
(файлы не залиты)