Вверх ↑
Этот топик читают: Гость
Ответов: 704
Рейтинг: 7
#31: 2019-01-10 15:13:58 ЛС | профиль | цитата
Очень интересно, но ничего не понятно
Стало быть такой вариант (если меня устраивают возможные пропуски событий на оконные элементы) более стабильный?
Add(MainForm,2141225,63,84)
{
link(onCreate,6433643:doStart,[(193,104)(193,132)])
}
Add(StrCat,11865489,455,196)
{
link(onStrCat,2921077:doWork,[(536,202)(536,209)])
link(Str1,4120622:Value,[])
}
Add(Memory,4120622,455,133)
{
}
Add(DeferredEvent,3925797,378,196)
{
link(onDeferredEvent,11865489:doStrCat,[])
}
Add(Thread,6433643,203,126)
{
Delay=100
link(onExec,11129683:doNext,[])
link(onSyncExec,3925797:doDeferredEvent,[(249,139)(249,202)])
}
Add(Hub,718859,315,126)
{
@Color=9371647
link(onEvent1,13209962:doWork,[(340,132)(340,118)])
link(onEvent2,4120622:doValue,[])
}
Add(InfoTip,8739713,525,175)
{
Info=#42:События на визуальные элементы или чтение |52:данных от параллельных потоков, пропуски допускаются|
Width=337
Height=53
}
Add(LineBreakEx,2921077,546,203)
{
}
Add(LineBreakEx,13209962,385,112)
{
Caption="Приоритетная обработка данных"
}
Add(Counter,11129683,259,126)
{
@Color=9371647
Max=999999999
link(onNext,718859:doEvent1,[])
}


Редактировалось 3 раз(а), последний 2019-01-10 15:16:44
карма: 0

0
Разработчик
Ответов: 26113
Рейтинг: 2126
#32: 2019-01-10 15:28:29 ЛС | профиль | цитата
Neo писал(а):
Стало быть такой вариант (если меня устраивают возможные пропуски событий на оконные элементы) более стабильный?

Оригинальное решение. В принципе, тк DiferredEvent использует PostMessage, то вызов отложенного события не будет влиять на параллельный поток. Чсзать, теоретически, это можно делать и из самого параллельного потока, тк не надо будет ждать ответа от основного потока и событие onDiferredEvent никак не связано с параллельным потоком, а является продолжением цепочки событий обработчика главного потока.

Интересно бы послушать Netspirit-a по этому вопросу, че он скажет.
карма: 22

0
Ответов: 4628
Рейтинг: 749
#33: 2019-01-10 15:30:24 ЛС | профиль | цитата
DeferredEvent можно и прямо из onExec вызывать (пока писал - nesco то же ответил). Но все равно есть проблемы:
- частый вызов забивает очередь сообщений (а это пропуск не только от DeferredEvent, но возможно и других, типа нажатий клавиатуры). В общем, признак плохого приложения.
- есть конфликт потоков при доступе к Memory: параллельный поток пишет, главный поток из DeferredEvent читает. Может быть нарушение данных. Хотя, вероятность такого для тебя может оказаться приемлемой. Подобные места надо защищать SafeMode.

Я лично предпочел бы таймер с защитой Memory по SafeMode.

С SafeMode следует учитывать такое. Если SafeMode используется также из главного потока (например, после DeferredEvent в той схеме), то в параллельном потоке в его SafeMode нельзя обращаться к главному потоку (оконным элементам, другим компонентам, которые шлют сообщения) - будет dead lock (главный поток останавливается в ожидании входа в критическую секцию, а параллельный поток, заняв эту секцию, останавливается в ожидании обработки сообщений главным потоком). Как я понимаю, SafeMode в главном потоке лучше не использовать.

Редактировалось 6 раз(а), последний 2019-02-04 13:21:06
карма: 26

0
Разработчик
Ответов: 26113
Рейтинг: 2126
#34: 2019-01-10 15:37:09 ЛС | профиль | цитата
Netspirit писал(а):
параллельный поток пишет, главный поток из DeferredEvent читает - может быть наружение данных

Это если нет задержки, если же есть задержка, как в примере -- 100 мсек, то параллельный поток уснет на это время и никуда лезть не будет.
Netspirit писал(а):
Подобные места надо защищать SafeMode

При наличии задержки, SafeMode нужен будет для разных потоков с одним значением задержки.

Редактировалось 1 раз(а), последний 2019-01-10 15:40:45
карма: 22

0
Ответов: 4628
Рейтинг: 749
#35: 2019-01-10 15:42:37 ЛС | профиль | цитата
nesco писал(а):
Это если нет задержки, если же есть задержка
Всего лишь уменьшается вероятность ошибки (которая может быть приемлемой). Я считаю, что программист не должен писать код, который полагается на время исполнения кода (а также на взаимный порядок исполнения разных потоков, если явно об этом не позаботится).
Скажем, параллельный поток 100 раз вызвал DeferredEvent, из них 50 подряд дошли до очереди сообщений. Затем главный поток завершил обработку предыдущих сообщений и приступил к выборке этих 50-ти - без всяких задержек, а тупо подряд. А теперь если параллельный поток во время этих 50-ти чтений Memory всего один раз запишет в неё данные (после своей задержки) - мне кажется, вероятность встречи этих 2-х потоков достаточно высокая.
И да, речь о Memory. А если там будет StrList или MemoryStream с их перевыделениями памяти?

Редактировалось 2 раз(а), последний 2019-01-10 15:47:38
карма: 26

0
Разработчик
Ответов: 26113
Рейтинг: 2126
#36: 2019-01-10 15:49:38 ЛС | профиль | цитата
Netspirit писал(а):
Скажем, параллельный поток 100 раз вызвал DeferredEvent, из них 50 подряд дошли до очереди сообщений.

Интересно, как он их 100 раз вызовет при задержке в 100 мсек так, чтобы до главного потока дошла только половина отложенных сообщений? Да за эти 100 мсек вся система не один обработчик обслужит по нескольку раз, если только там мертвых циклов не понаставить. КМК, твой случай правильный тогда, когда параллельный поток работает непрерывно, те с нулевой задержкой.

Редактировалось 4 раз(а), последний 2019-01-10 16:03:42
карма: 22

0
Ответов: 704
Рейтинг: 7
#37: 2019-01-10 16:17:56 ЛС | профиль | цитата
Netspirit писал(а):
Я лично предпочел бы таймер с защитой Memory по SafeMode.

Помню эту рекомендацию с осени этого года и перевел все подобные места на SafeMode. Проблемы ошибок не ушли совершенно, только еще зависания добавились. Решил что нужно их поставить везде в таких местах даже на главном потоке дабы найти ошибку доступа (хуже мол не будет). И стало таки хуже. Как будто сами сейфмоды на главном потоке портили всю малину. Убрал сейфмоды на неделе и работать стало заметно стабильнее.
карма: 0

0
Ответов: 4628
Рейтинг: 749
#38: 2019-01-10 16:18:25 ЛС | профиль | цитата
nesco писал(а):
твой случай правильный тогда, когда параллельный поток работает непрерывно, те с нулевой задержкой.
Действительно. Вот только задержка в данном примере - это "сферический конь в вакууме". В реальной программе получается ты сознательно замедляешь обработку. Это допустимо до тех пор, пока у тебя параллельный поток выполняет задачу "выполнять некоторое действие в цикле с задержкой". Как только задача выходит за эти рамки - так сразу подход оказывается неудачным. А вот если задачу перефразировать на "сообщать пользователю о процессе выполняемой потоком работы не перегружая главный поток и не сильно замедляя параллельный", тогда появляются другие варианты реализации.

Neo писал(а):
Как будто сами сейфмоды на главном потоке портили всю малину
Как я выше написал, с SafeMode в главном потоке нужно быть осторожным, а также он практически никак не помогает при доступе к визуальным компонентам из параллельных потоков (только Synchronize).

Редактировалось 2 раз(а), последний 2019-01-10 16:22:37
карма: 26

0
Ответов: 704
Рейтинг: 7
#39: 2019-01-10 16:26:22 ЛС | профиль | цитата
Netspirit писал(а):
будет dead lock (главный поток останавливается в ожидании входа в критическую секцию, а параллельный поток, заняв эту секцию, останавливается в ожидании обработки сообщений главным потоком). Как я понимаю, SafeMode в главном потоке лучше не использовать.

Главному потоку я ставил NoWait и он никого не ждал, просто пробовал снова через время. Но это так же неожиданно плохо сказывалось на стабильности, добавилась тормознутость в визуальных элементах. В варианте именно с чтением данных после параллельного потока по таймеру сейфмоды показались совершенно лишними.

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

0
Разработчик
Ответов: 26113
Рейтинг: 2126
#40: 2019-01-10 16:30:03 ЛС | профиль | цитата
Netspirit писал(а):
"сообщать пользователю о процессе выполняемой потоком работы не перегружая главный поток и не сильно замедляя параллельный", тогда появляются другие варианты реализации.

Использование в параллельном потоке синхронизации с главным через SendMessage запросто может привести к ситуации, когда уже главный поток тормознет параллельные, и это потому, что в главном потоке работает все приложение.

Редактировалось 2 раз(а), последний 2019-01-10 16:34:22
карма: 22

0
Ответов: 4628
Рейтинг: 749
#41: 2019-01-10 16:32:18 ЛС | профиль | цитата
Просто если в главном потоке есть SafeMode, то в параллельных потоках после одноименного SafeMode не следует делать ничего, что приводит к обращениям к главному потоку (например, обращаться к визуальным компонентам, в т.ч. через Synchronize)

nesco писал(а):
может привести к ситуации, когда уже главный поток тормознет параллельные
Да, или просто визуальные тормоза в интерфейсе. Следовательно, нужно минимизировать различными способами обращение к главному потоку из параллельного, а также "тяжесть" работы, выполняемой при таких обращениях.

Редактировалось 1 раз(а), последний 2019-01-10 16:35:16
карма: 26

0
Ответов: 704
Рейтинг: 7
#42: 2019-01-10 16:33:03 ЛС | профиль | цитата
nesco писал(а):
Использование в параллельном потоке синхронизации с главным через SendMessage запросто может привести к ситуации, когда уже главный поток тормознет параллельные, и это потому, что в главном потоке работает все приложение.

Когда пробовал ставить Synchronize во всех подозрительных участках, именно так и было.

--- Добавлено в 2019-01-10 16:34:09

Netspirit писал(а):
Просто если в главном потоке есть SafeMode, то в параллельных потоках после одноименного SafeMode не следует делать ничего, что приводит к обращениям к главному потоку (например, обращаться к визуальным компонентам, в т.ч. через Synchronize)

Так учитывал это. Только к мемори обращался или к SQLite с развязкой результатов через стек+таймер.

Редактировалось 2 раз(а), последний 2019-01-10 16:35:25
карма: 0

0
Разработчик
Ответов: 26113
Рейтинг: 2126
#43: 2019-01-10 16:34:14 ЛС | профиль | цитата
Тут получается -- и так хреново, и так не лучше.
NetSpirit, тебе не кажется, что мы что-то тут упускаем, чего-то тут явно не хватает?

Редактировалось 2 раз(а), последний 2019-01-10 16:44:16
карма: 22

0
Ответов: 4628
Рейтинг: 749
#44: 2019-01-10 16:37:41 ЛС | профиль | цитата
А по-моему ничего не упускаем. Очень поучительно рассматриваем все возможные варианты работы с параллельными потоками. Остаётся только применять в конкретных приложениях и смотреть что где не получается.

Сейчас попробую пару паттернов набросать.

Редактировалось 1 раз(а), последний 2019-01-10 16:38:54
карма: 26

0
Разработчик
Ответов: 26113
Рейтинг: 2126
#45: 2019-01-10 16:43:33 ЛС | профиль | цитата
Netspirit, у тебе никогда не возникало сомнения в точке Busy? Ну какого рожна эта точка выдает занятость, когда поток спит? Ведь эта точка работает по созданию и полному завершению работы потока, а не по действительной занятости.
Вот если бы эта точка работала по действительной занятости, то создав кольцо опроса, мы могли бы свободно обращаться к данным параллельных потоков, пока те спят, и не было никаких перекрестных обращений.
КМК, то вот это должно работать как-то так
   th.Tag := 0;
sleep(_prop_delay);
th.Tag := 1;

Редактировалось 6 раз(а), последний 2019-01-10 16:53:12
карма: 22

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