Вверх ↑
Этот топик читают: Гость
Ответов: 4347
Рейтинг: 678
#61: 2017-10-02 11:02:13 ЛС | профиль | цитата
Galkov писал(а):
А я бы в его элементе добавил бы анализ потока из которого идет вызов doSynchronize, и если из основного - делал бы PostMessage.
В этом случае отличается логика работы метода "выполнить событие и дождаться завершения" - в другом случае может быть "выполнить событие (когда-то в будущем) не дожидаясь завершения". По-моему, это может вызвать проблемы порядка работы последующей схемы. Просто PostMessage можно отдельным методом, если нужно (типа, doSyncDeffered). Не заметил, что и так речь идёт об отдельном методе.
Пока что не имею других соображений.

У меня есть ещё такой вопрос. Как обрабатываются сообщения при завершении программы, а именно после получения WM_QUIT? Если поток посылает синхронизирующее событие после WM_QUIT - что происходит?
1) Сообщение попадает в очередь, поток блокируется, но сообщение не отрабатывается, так как цикл выборки сообщений уже прекратил работу
2) SendMessage выдаёт ошибку, сразу возвращая потоку управление

Я тут столкнулся с тем, что сложно корректно остановить работу потоков внутри компонентов при закрытии программы. Возникла идея, что перед вызовом hiXXXX1234.Destroy компонентов в файле формы вызывать какую-то глобальную функцию типа WaitForTreadsTerminate, размещённую в Share в виде переменной, куда какой-то модуль может прописать свою функцию. Классы потоков добавляют/удаляют себя из глобального списка потоков, а такая функция всем потокам в этом списке подаёт команду "завершить работу".

Редактировалось 4 раз(а), последний 2017-10-02 11:15:10
карма: 25

0
Ответов: 9906
Рейтинг: 351
#62: 2017-10-02 13:28:41 ЛС | профиль | цитата
Netspirit писал(а):
В этом случае отличается логика работы метода "выполнить событие и дождаться завершения" - в другом случае может быть "выполнить событие (когда-то в будущем) не дожидаясь завершения". По-моему, это может вызвать проблемы порядка работы последующей схемы. Просто PostMessage можно отдельным методом, если нужно (типа, doSyncDeffered).

Да отличается. И должна отличаться. Хотя коды отличаются всего на 4 буквы.
Deferred Event это и есть "выполнить событие (когда-то в будущем) не дожидаясь завершения".
А Synchronize это "выполнить событие и дождаться завершения".
Разница мелодий в этой схеме:
Add(MainForm,2070834,91,91)
{
link(onCreate,2559580:doStart,[])
}
Add(Synchronize,16055947,329,105)
{
link(onSync,2849320:doEvent1,[])
}
Add(Thread,2559580,140,105)
{
link(onExec,16075278:doWork1,[])
link(onSyncExec,16075278:doWork2,[])
}
Add(CounterEx,16407686,413,105)
{
link(onNext,2070834:doCaption,[(452,111)(452,83)(81,83)(81,97)])
}
Add(Hub,7916229,294,105)
{
link(onEvent1,16055947:doSynchronize,[])
link(onEvent2,9846986:doBeep,[(319,118)(319,153)])
}
Add(Hub,2849320,378,105)
{
link(onEvent1,16407686:doNext,[])
link(onEvent2,3125880:doBeep,[(403,118)(403,153)])
}
Add(CheckBox,12700623,238,56)
{
Left=28
Top=21
Width=97
Caption="Deferred"
}
Add(Beep,9846986,329,147)
{
Freq=300
Duration=200
}
Add(Beep,3125880,413,147)
{
Freq=1300
Duration=200
}
Add(ChanelToIndex,16075278,189,105)
{
link(onIndex,1571423:doCompare,[])
}
Add(If_else,1571423,238,105)
{
link(onTrue,7916229:doEvent1,[])
link(Op1,12700623:Checked,[])
}
-- это правильно. Это вовсе не "проблемы порядка работы последующей схемы".
А именно так это все и задумывалось.

Netspirit, ты же doSynchronize не имеешь право вызывать в своем элементе из главного потока. Потому-что получишь DeadLock.
И еще надо будет разобраться "почему программа зависла", ведь DeadLock далеко не единственный способ повесить программу...
И предлагается "рабоче-крестьянская" логика: если ты не можешь дождаться завершения (потому что в главном потоке его завершение может быть только после твоего - а ты ждешь), то давай не будем ждать, и пускай делается само. Вообще-то, вполне разумное решение, при отсутствии альтернатив. И эта "другая логика" настолько небесполезна, что nesco аж целый элемент для этого соорудил. В котором как и ты (как и Кладов) регистрировал сообщение, писал обработчик для окна, и т.п..

Поэтому непонятно, где ты увидел проблемы.
Как бы наоборот, повышается дуракоустойчивость - вместо DeadLock-а просто получаешь Deferred Event на выходе. С которым уже проще разобраться (программа то дышит, а не тупо висит).
Хотя, безусловно, программирование - это не для тех, кто работает методом тыка.

Netspirit писал(а):
У меня есть ещё такой вопрос.

У меня на это нет ответа. И вроде бы - и не может быть. Не документируют они это, оставляя за собой свободу действий. Есть слухи, гипотезы, некоторые соображения.
Предположим, что остались необработанные сообщения при получении WM_CLOSE. Это и сообщения какого-то таймера, и Deferred Events, и какое-то количество потоков, пытающихся синхронизироваться (хотя мне раньше казалось, что сообщения от SendMessage обрабатываются "вне очереди").
Если честно, я не увидел особого отличия необработанного WM_PAINT, от убийства потока безжалостным Terminate.
В подавляющем большинстве случаев.

Согласен, возможна более тонкая работа в потоках. Но мне непонятно, почему это должно быть общей парадигмой (мне показалось, что именно всеобъемлющая парадигма является Вашей головной болью в последнее время). В конце концов, кроме интернета существует много других интересных вещей.
Как надо это решать, мне думается...
Заводить отдельный сервер, в котором регистрируются особо чувствительные парни. И которые, соответственно, предоставляют ему метод "аккуратной остановки".
А сервер запускает процесс всех "аккуратных остановок", перехватив Close от MainForm.
Это все я говорил как бы про технологию менеджеров в HiAsm.

Редактировалось 6 раз(а), последний 2017-10-02 14:03:09
карма: 9

0
Ответов: 4347
Рейтинг: 678
#63: 2017-10-02 14:17:10 ЛС | профиль | цитата
Galkov писал(а):
Это вовсе не "проблемы порядка работы последующей схемы".
Я это имел в виду исключительно по отношению к методу doSynchronize, не заметив, что это предлагалось отдельно в виде doDeferred.

Galkov писал(а):
именно всеобъемлющая парадигма является Вашей головной болью в последнее время
Ага. Чтобы каждый разработчик компонентов не решал это заново.

Galkov писал(а):
Предположим, что остались необработанные сообщения при получении WM_CLOSE
Чисто для понимания: кроме WM_CLOSE есть ещё и WM_QUIT.

Galkov писал(а):
Netspirit, ты же doSynchronize не имеешь право вызывать в своем элементе из главного потока. Потому-что получишь DeadLock.
Я вот сколько вчитываюсь, не могу понять - почему? Какой это deadlock по WM_CLOSE и SendMessage?

Редактировалось 1 раз(а), последний 2017-10-02 14:18:04
карма: 25

0
Ответов: 9906
Рейтинг: 351
#64: 2017-10-02 14:33:04 ЛС | профиль | цитата
Netspirit писал(а):
Какой это deadlock по WM_CLOSE и SendMessage?

Причем тут за рыбу деньги
Утверждение "ты же doSynchronize не имеешь право вызывать в своем элементе из главного потока" было ДО обсуждения про WM_CLOSE (или пусть WM_QUIT)

Забудь на минуту "про парадигму". Пусть будут мухи отдельно, котлеты - отдельно.
Просто, делая Thread.Synchronize из главного потока ты получаешь DeadLock.
И ВСЕ. Никаких других уточнений, разве это не является просто экспериментальным фактом
Хотя... Это же очевидно их без экспериментов.

Netspirit писал(а):
не заметив, что это предлагалось отдельно в виде doDeferred.

Было, предлагалось (в этом посте). Пока не дошло, что делать отдельно нет необходимости.
Потом уже (здесь) предлагалось НЕ делать отдельно, а делать вместе

Редактировалось 3 раз(а), последний 2017-10-02 14:49:17
карма: 9

0
Ответов: 4347
Рейтинг: 678
#65: 2017-10-02 14:48:32 ЛС | профиль | цитата
Galkov писал(а):
ты же doSynchronize не имеешь право вызывать в своем элементе из главного потока
Вот этого я и не понимаю. С какого это перепугу? Вот в этой схеме я именно это и делаю:

Add(MainForm,2953706,21,105)
{
Position=1
}
Add(Button,682534,112,105)
{
Left=65
Top=55
link(onClick,12488891:doSynchronize,[])
}
Add(Label,1847038,245,105)
{
Left=150
Top=55
}
Add(Synchronize,12488891,175,105)
{
link(onSync,1847038:doText,[])
link(Data,6437121:Value,[])
}
Add(Memory,6437121,175,56)
{
Default=String(AAA)
}
карма: 25

0
Ответов: 9906
Рейтинг: 351
#66: 2017-10-02 14:52:32 ЛС | профиль | цитата
Кстати говоря, схема моего предыдущего поста предполагает последнюю реализацию.
А если это оригинальный Synchronize (Ваш) -- то должен быть DeadLock
Неужели нет
карма: 9

0
Ответов: 4347
Рейтинг: 678
#67: 2017-10-02 14:54:10 ЛС | профиль | цитата
Оригинальный. И нет, дедлока быть не должно, иначе у нас бы не работал ни один визуальный компонент. При вызове SendMessage из главного потока сообщение минует очередь сообщений и напрямую вызывается оконная процедура соответствующего окна.
карма: 25

0
Ответов: 9906
Рейтинг: 351
#68: 2017-10-02 16:17:57 ЛС | профиль | цитата
Точно, блин, переклинило меня на этой синхронизации.
Это помню: "If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message."
А эту банальность "If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine" -- исхитрился позабыть.

Три раза КУ

Тем не менее чего-то тут все-таки осталось.
Элемент Synchronize несколько теряет смысл при вызове из главного потока.
((Про DeadLock был неправ, готов искупить и загладить!!!))
Это по функционалу просто DoData.
Поэтому "совмещение" продолжает иметь некоторый смысл.
Хотя теперь уже - не настолько аргументированный

Редактировалось 2 раз(а), последний 2017-10-02 16:19:44
карма: 9

0
Ответов: 4347
Рейтинг: 678
#69: 2017-10-02 16:25:09 ЛС | профиль | цитата
Просто DefferedEvent для "асинхронной синхронизации" как-то более привычней, что-ли, так что объединять необязательно.
карма: 25

0
Разработчик
Ответов: 25681
Рейтинг: 2087
#70: 2017-10-03 11:50:37 ЛС | профиль | цитата
Так к чему пришли, многоуважаемые кроты? Оставляем все как есть с Synchronize, а DefferedEvent я переделываю на новый алгоритм, или будут еще какие предложения? Или Synchronize тоже переделывать собрались, ну тут уже Netspirit пусть сам озаботится.

Редактировалось 1 раз(а), последний 2017-10-03 11:52:33
карма: 20

0
Ответов: 4347
Рейтинг: 678
#71: 2017-10-03 13:14:22 ЛС | профиль | цитата
По поводу Synchronize.
С одной стороны: работает - не трожь.
С другой: если тебе чисто внутренне больше нравится реализация Galkov-а, можно заменить.

Лично мне не очень нравится такой подход по следующим причинам:
- не очень "чистоплотная" реализация с подставным объектом
- отсутствует глобальная функция CallSynchronized, которую я добавил для использования этого функционала из других компонентов с собственной реализацией потоков. Например, асинхронный вызов может приходить из DLL, типа BASS, и компонент внутри себя захочет сообщить о нём в схему синхронно.
- не знаю, насколько актуально, но KOL-овский метод Synchronize не работает в неоконных приложениях. В моей реализации это учтено и событие все равно вызывается, но асинхронно. При необходимости туда можно добавить синхронизацию даже для неоконных приложений.
карма: 25

0
Разработчик
Ответов: 25681
Рейтинг: 2087
#72: 2017-10-03 13:47:22 ЛС | профиль | цитата
Netspirit писал(а):
С одной стороны: работает - не трожь.

Раз автор сказал, значит, Synchronize не трогаем.
карма: 20

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