Я использую правильный подход для контроля задач, которые я хочу выполнить, когда дескриптор создается?

8 ответов

Грег,

То, что у вас есть , не шаблон наблюдателя, а скорее очередь сообщений. Значит, вы просто используете неправильный шаблон проектирования для проблемы, которую пытаетесь решить.

Достаточно легко реализовать собственную очередь сообщений с нуля, используя Queue {Action {object}} , где объекты ставятся в очередь сами, а вы просто удаляете их из очереди по мере их вызова.

11
ответ дан 8 December 2019 в 17:23
поделиться

Обычный способ - сохранить логическое значение, указывающее, должно ли оно выполняться ...

bool runMyEvent = true;

void Handler(object sender, EventArgs e) {
   if (runMyEvent) {
      // handler here
      runMyEvent = false;
   } else {
      return;
   }
}
1
ответ дан 8 December 2019 в 17:23
поделиться

Здесь вы можете использовать метод однократного запуска, упомянутый здесь несколько раз, но с этим есть несколько проблем, в зависимости от вашего варианта использования.

1) Возможно, вы захотите повторно -зацепите метод позже и снова запустите его. Хотя я полагаю, что вы можете сбросить свой bool

2) У вас все еще есть эта ссылка, которая может в конечном итоге сохранить ваш класс в памяти вместо того, чтобы собирать мусор.

Один из вариантов - использовать анонимный метод и закрытие, когда вы определяете обработка событий:

public class Foo
{
    public EventHandler<EventArgs> MyEvent;

    public void FireEvent()
    {
        if(MyEvent != null)
            MyEvent(this, EventArgs.Empty);
    }
}

Foo obj = new Foo();

Action<object, EventArgs> action = new Action<object, EventArgs>((sender, args) =>
{
    // We're now running the event handler, so unsubscribe
    obj.MyEvent -= new EventHandler<EventArgs>(action);

    // Do whatever you wanted to do when the event fired.
});

obj.MyEvent += new EventHandler<EventArgs>(action);
1
ответ дан 8 December 2019 в 17:23
поделиться

как насчет обработчика, который запускается только один раз? Примерно так:


if (wasRun)
    return;
wasRun = true;

1
ответ дан 8 December 2019 в 17:23
поделиться

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

Не знаю, хорошая ли это идея, просто еще одна мысль.

0
ответ дан 8 December 2019 в 17:23
поделиться

Вы можете использовать объекты WeakReference, чтобы представить, так сказать, слабых подписчиков . Во время запуска события вы можете проверить, была ли уже собрана слабая ссылка, и при необходимости удалить этого подписчика из списка подписчиков.

Основная идея заключается в том, что когда подписчики собираются GC, ваш обработчик заметит это и выбросит их вне списка подписчиков.

0
ответ дан 8 December 2019 в 17:23
поделиться

На CodeProject есть подробная статья: Слабые события , в которой рассматриваются несколько решений этой проблемы.

0
ответ дан 8 December 2019 в 17:23
поделиться

Я обычно делаю что-то вроде следующего, чтобы реализовать однократный обработчик событий.

void OnControlClickOneTime(this Control c, EventHandler e) {
  EventHandler e2 = null;
  e2 = (s,args) => {
    c.Click -= e2;
    e(s,args);
  };
  c.Click += e2;
}
0
ответ дан 8 December 2019 в 17:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: