Re: Размножающиеся события
От: white_znake  
Дата: 29.08.21 21:27
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:


ЭФ>Если для просто объектов в памяти придумали сборку мусора, то как поступают с событиями?


Если заботишься об утечках памяти, то посмотри, не поможет ли тебе WeakEventReference?
Re[5]: Размножающиеся события
От: vaa  
Дата: 30.08.21 02:01
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>Я не хочу кустарные примеры. Я хочу всесторонне проработанную технологию.


Может что-то из этого:








Последняя еще не в релизе, но выглядит симпатично.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re: Размножающиеся события
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.08.21 07:50
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>Если есть сеть объектов, которые уведомляют друг друга при помощи событий,

ЭФ>то как всем этим управляют? Дело в том, что если возникает одно событие,
ЭФ>оно при распространении генерирует вторичные события в сети объектов,
ЭФ>те события в свою очередь генерируют новые события и всё это размножается до невозможности.

ЭФ>Если для просто объектов в памяти придумали сборку мусора, то как поступают с событиями?

Ну, вообще говоря, возможны два варианта:
1. Граф порождения событий ацикличен — тогда бесконечный рост невозможен. Рано или поздно все события дойдут до конца своих цепочек.
2. В графе порождения событий есть циклы — тогда возникает бесконечный рост (или как минимум неубывание количества сообщений), и система затыкается.

Свойства графа — штука относительно статическая. Всё управление сводится к обнаружению и разрыванию циклов.

Обнаружение зависит от того, на чём строятся события. Может быть, у вас будет переполнение стека; может быть — out of memory, может быть — забивание очереди.

Способ разрыва цикла делается по-разному.
Для начала можно попытаться ввести классы событий, и сделать так, чтобы порождение событий обязано было менять "класс" только в одну сторону.
Ну, там — из обработчика события "файл изменился" мы можем породить событие "нужно добавить запись в лог", а вот из обработчика события "добавляем запись в лог" мы не имеем права порождать событие "файл изменился".

Иногда бывает так, что так сделать нельзя — изменения должны работать "в обе стороны". Например, в тех местах, где события делаются для синхронизации значений, обычно достаточно сделать проверку на изменение:
public void OnChangeX(int value)
{
  if (x == value) return; // don't propagate a no-change!
  x = value;
  RaiseOnXChanged(x); // notify all the subscribers so they can reflect a new value of X.
}

Без первой строки у нас есть риск того, что кто-то из подписчиков поменяет своё значение, и сгенерирует новое OnChangeX(), свалив систему в бесконечный цикл. А при особенной удаче можно даже получить экспоненциальный рост количества необработанных сообщений.

Но такое работает в предположении однозначности устанавливаемого значения — мы легко отличаем ситуацию "уже обработано" от "ой, нет, ещё не обработано". Возможно, в цепочке будут противоречия — например, из-за округления.
Типа уменьшили ширину окна -> вложенные окна перестали влезать -> показали скролл-бар -> уменьшилась ширина окна -> одно из вложенных окон решило свернуться -> окна начали влезать -> убрали скролл-бар -> вложенное окно решило развернуться и т.п.
Для таких случаев лучше уходить от лэйаута на событиях к лэйаут менеджерам, которые видят одновременно всю "систему уравнений", и решают её без циклических согласований.

Для более общего случая, когда нет возможности отказаться от событий, и при этом мы не можем легко отличить "новое" событие от его "реплики", можно пользоваться различными способами.
Самый простой — TTL, как уже предложили. То есть после N итераций мы гарантированно прекращаем обработку события.
Достоинство — не надо выделять память под хранение предыстории. Недостаток — для маленьких N у нас есть риск не добраться до конца валидной цепочки сообщений; для больших — у нас всё ещё есть риск выполнить в N/2 (или N/3) больше работы, чем необходимо.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Размножающиеся события
От: Эйнсток Файр Мухосранск Странный реагент
Дата: 30.08.21 09:10
Оценка:
S> Свойства графа — штука относительно статическая.

Только граф событий не статический, и строится он поверх модели, которая тоже не статическая...
Re[3]: Размножающиеся события
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.08.21 09:16
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

S>> Свойства графа — штука относительно статическая.


ЭФ>Только граф событий не статический, и строится он поверх модели, которая тоже не статическая...

Ну, поэтому я и написал — относительно статический
Не видя конкретного примера, трудно угадать, какая доля связей известна заранее, а какая — возникает на лету.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Размножающиеся события
От: Эйнсток Файр Мухосранск Странный реагент
Дата: 30.08.21 10:10
Оценка:
А вот зачем было вообще вводить в язык такой синтаксис? Тем более, что функции отдельно всё равно потом по-другому добавили (Func<TResult>).
Наверное же хотели как лучше.

А если признали, что вышло плохо, наверное надо весь UI переделать по-новому?
Re[5]: Размножающиеся события
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.08.21 10:49
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>А вот зачем было вообще вводить в язык такой синтаксис? Тем более, что функции отдельно всё равно потом по-другому добавили (Func<TResult>).

ЭФ>Наверное же хотели как лучше.
ЭФ>А если признали, что вышло плохо, наверное надо весь UI переделать по-новому?
Вот сейчас не понял, о чём речь.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Размножающиеся события
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.08.21 20:27
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>А вот зачем было вообще вводить в язык такой синтаксис? Тем более, что функции отдельно всё равно потом по-другому добавили (Func<TResult>).

ЭФ>Наверное же хотели как лучше.
Хотели, как быстрее. События (о них же речь) были пересены в первую версию C# по мотивам Delphi и MFC. Дженерики появились лишь во второй. Т.е. Func<TResult> стало возможно гораздо позже.

ЭФ>А если признали, что вышло плохо, наверное надо весь UI переделать по-новому?

Да не так уж и плохо вышло, если смотреть на другие мертвые переделки UI.
Re: Размножающиеся события
От: Vladek Россия Github
Дата: 06.10.21 05:34
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>Если есть сеть объектов, которые уведомляют друг друга при помощи событий,

ЭФ>то как всем этим управляют? Дело в том, что если возникает одно событие,
ЭФ>оно при распространении генерирует вторичные события в сети объектов,
ЭФ>те события в свою очередь генерируют новые события и всё это размножается до невозможности

Это разветвители.

ЭФ>Если для просто объектов в памяти придумали сборку мусора, то как поступают с событиями?


Этим занимается агрегатор.

Есть замечательная книга "Шаблоны интеграции корпоративных приложений" аж 2003 года издания, где все эти приёмы описаны.
Re: Размножающиеся события
От: Pitirimov США  
Дата: 12.10.21 08:43
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:
ЭФ>Если для просто объектов в памяти придумали сборку мусора, то как поступают с событиями?

Очередь сообщений всегда имеет конечный размер. Когда количество сообщений превысит максимальный размер очереди, то положить новое сообщение в очередь станет невозможным. На читающей стороне можно читать и отрабатывать все сообщения разом, накопившиеся на данный момент времени, чтобы очередь сообщений опорожнялась полностью при чтении. Всё просто, ребята.
Отредактировано 11.03.2022 10:33 Pitirimov . Предыдущая версия . Еще …
Отредактировано 12.10.2021 9:22 Pitirimov . Предыдущая версия .
Отредактировано 12.10.2021 9:21 Pitirimov . Предыдущая версия .
Отредактировано 12.10.2021 8:44 Pitirimov . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.