Вопрос о пользовательских событиях - PullRequest
5 голосов
/ 07 мая 2010

Я делаю собственные события для C #, и иногда это не работает.

Вот как я делаю событие:

    private bool isDoorOpen;
    public bool IsDoorOpen {
        get { return isDoorOpen;}
        private set { isDoorOpen = value; DoorsChangeState(this, null);}
    }

И это событиеобъявления:

    //events        
    public delegate void ChangedEventHandler(Elevator sender, EventArgs e);
    public event ChangedEventHandler PositionChanged;
    public event ChangedEventHandler DirectionChanged;
    public event ChangedEventHandler BreaksChangeState;
    public event ChangedEventHandler DoorsChangeState;

Это работает до тех пор, пока есть методы, прикрепленные к событиям, но если нет, выдает исключение null ref.Что я делаю не так?

Ответы [ 5 ]

10 голосов
/ 07 мая 2010

Рекомендуемый способ вызова события -

var handler = this.DoorsChangeState;
if (handler != null)
    handler(this, null);

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

РЕДАКТИРОВАТЬ: Нашел статью, рассказывающую об условиях гонки. http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

4 голосов
/ 07 мая 2010

Я знаю, что этот вопрос обсуждался (и отвечался) несколько раз здесь, на SO.

Также где-то здесь у меня есть следующие методы расширения, чтобы сделать этот шаблон более простым в использовании:

public static class EventHandlerExtensions
{
    public static void FireEvent<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
    {
        var temp = handler;
        if (temp != null)
        {
            temp(sender, args);
        }
    }

    public static void FireEvent(this EventHandler handler, object sender)
    {
        var temp = handler;
        if (temp != null)
        {
            temp(sender, EventArgs.Empty);
        }
    }
}

Итак, в вашем коде вы можете сказать:

public bool IsDoorOpen
{
    get { return isDoorOpen;}
    private set
    {
        isDoorOpen = value;
        DoorsChangeState.FireEvent(this);
    }
}
0 голосов
/ 07 мая 2010

Вам необходимо проверить, подписано ли событие на

.

Я использую эту стандартную форму для броска всех моих событий.

var temp = EventName;
if(EventName!= null)
   temp(this, null);
0 голосов
/ 07 мая 2010

Перед вызовом события вы должны проверить, является ли событие нулевым:

if (DoorsChangeState != null)   
  DoorsChangeState(this, null);

Когда DoorsChangeState равно нулю, это означает, что на этом событии нет слушателей.

0 голосов
/ 07 мая 2010

Если событие не подписано на момент его возникновения, генерируется исключение NullReferenceException Это правильное поведение, а не то, что вы сделали неправильно.

Вы должны проверить:

if(DoorsChangeState != null)
{
   DoorsChangeState(this, null); // Only fire if subscribed to
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...