C # - Обеспечение того, чтобы события не складывались - PullRequest
2 голосов
/ 18 марта 2011

HI,

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

Эта кнопка используется много раз, и я нене хочу, чтобы события складывались.Поэтому я отменил подписку на событие в блоке finally.

Код похож на приведенный ниже:

try {
bar = new foo();
bar.event += new event(method);

dosomething()
}
finally {
bar.event -= new event(method);
}

Пока все работает нормально, однако меня беспокоит вопросблок обрабатывается до завершения метода doSomething и, таким образом, использует событие.

Будет ли разрешено обрабатывать метод до вызова блока finally?

Ответы [ 8 ]

6 голосов
/ 18 марта 2011

Обычно я использую логическую переменную inEvent, которая проверяется при каждом запуске события.Код будет выглядеть так:

bool inEvent = false;

...

private void Button1_Click(object source, EventArgs e) 
{
    if (inEvent)
        return;

    try 
    {
        inEvent= true;

        dosomething();
    }
    finally 
    {
        inEvent = false;
    }
}
3 голосов
/ 18 марта 2011

Блок finally будет выполнен, когда

  1. dosomething успешно завершено
  2. dosomething создает исключение
  3. конструктор foo выдает исключение

В последнем случае он получит доступ к неинициализированной переменной bar и выдаст исключение NullReferenceException Так что лучше поместите bar = new foo(); перед блоком try.

2 голосов
/ 18 марта 2011

блок finally по определению может быть превышен только после того, как выполнение покинуло тело метода dosomething (), будь то с помощью оператора return или нормального конца функции или исключения, которое выдается в теле этого метода, которое не обрабатывается в этой функции.

1 голос
/ 18 марта 2011

Лучше отписаться в сгенерированном событии.

void somewhere()
{
    bar = new foo();
    bar.event += method;
    dosomething()
}

void method(object source, EventArgs e)
{
    ((bar)source).event -= method;
}
1 голос
/ 18 марта 2011

Блок finally не будет работать до тех пор, пока dosomething не вернет или не выбросит.

0 голосов
/ 18 марта 2011

События вызываются синхронно.Поэтому, если вы не пишете какой-либо асинхронный код в своем методе DoSomething(), в конечном итоге всегда будет выполняться после завершения выполнения (или выдается исключение).Это означает, что ссылки на обработчики событий будут препятствовать сбору объекта, что может вызвать проблемы с памятью.У вас есть правильная идея, что для того, чтобы полностью освободить объект, вы должны удалить все события после того, как с ним покончено.

0 голосов
/ 18 марта 2011

Предположительно, логика в DoSomething () вызывает интересующее вас событие?Если это так, у вас возникнет проблема, если DoSomething () вызовет событие асинхронно - если это так, вполне вероятно, что DoSomething вернется, тогда ваш finally будет запущен и отписаться от события.Когда событие в конечном счете инициируется из кода, инициированного в DoSomething, вы пропустите его.

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

0 голосов
/ 18 марта 2011

Да (если, конечно, перед этим не выдается исключение).Ваша идея здорова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...