2010-06-17 4 views
3

Зачем нужно публичное событие EventHandler cccc?Зачем нужно публичное событие EventHandler cccc?

У меня есть класс, который это

public class Builder 
{ 
    public event EventHandler StartedWorking; 

    public Builder() 
    { 
     // Constructor does some stuff 
    } 

    public void Start() 
    { 
     StartedWorking(this, eventargobject); //StartedWorking is null -- 
    } 
} 

Это кажется простым и что-то я все время? Я пропустил что-то очевидное или есть что-то, что может вызвать это?

EDIT:

Означает ли это, что если я огонь событие, которое не подписался в классе клиента я должен проверить, что это не пустой?

EDIT-2:

Я предполагаю, что я никогда бы не было событий, которые никогда не были не подписаны и, следовательно, никогда не столкнулся с этим - Вы узнаете что-то новое каждый день Sorry о, казалось бы, глупый вопрос ....

+0

Matt: Что касается вашего редактирования - я добавил «правильный» способ поднять события на мой ответьте за вас. Сначала вы должны сначала проверить значение null. –

ответ

11

Обработчик событий будет иметь значение null, если кто-то не подписался на это событие. Как только делегат будет подписан на мероприятие, он больше не будет равен нулю.

Вот почему это всегда предлагается использовать следующую форму для повышения события:

public void Start() 
{ 
    var handler = this.StartedWorking; 
    if (handler != null) 
    { 
     handler(this, eventArgObject); 
    } 
} 

Это защищает Вас от нулевого исключения, если не было никаких абонентов.

+4

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

0

Если вы не подключили подписчиков событий до вашего события StartedWorking, это будет null. Так работают .NET-события.

This article, среди прочего, демонстрирует, что перед вызовом события необходимо проверить значение null. This other question and answer демонстрирует, как вы можете создавать события таким образом, чтобы избежать нулевой проверки (в основном путем добавления пустого обработчика всегда).

+0

В первой статье (из .NET 1.1) показано, как это сделать, но это неуместно в многопоточных ситуациях. Вместо этого я рекомендую свой подход. Вторая статья работает, но может быть хрупкой (можно удалить этого обработчика, что вызовет исключение снова), плюс добавляет накладные расходы каждый раз, когда вы поднимаете событие (вызов делегата). –

0

Вам не нужно назначать функцию?

StartedWorking += new EventHandler(afunction); 

void afunction(object sender, EventArgs e) 
{ 
    DoSomething(); 
} 
2

Как уже говорилось, это значение равно нулю, поскольку подписчиков нет.

Чтобы ответить на ваше изменение: Да, вы должны всегда проверять событие за нуль, прежде чем запускать его. Однако, если вы просто делаете простой if(StartedWorking != null){...}, вы рискуете условием гонки, потому что абонент может отказаться от подписки после нулевой проверки, но перед запуском события. Из-за этого, вы всегда должны использовать этот шаблон при проверке событий для нуля:

protected void OnStartedWorking() 
{ 
    EventHandler localEvent = StartedWorking 
    if(localEvent != null) 
    { 
     localEvent(this, EventArgs.Empty); 
    } 
} 

Это предотвращает состояние гонки, взяв копию события первой, так что список подписки фиксируются в момент копирования.

Там больше infomration о публикации событий на MSDN: How to Publish Events that Conform to .NET Framework Guidelines

(Это работает, потому что в.net the MultiCastDelegate класс в imutable, поэтому любая попытка изменить список подписчиков на мероприятии не повлияет на копию, которую вы сделали)

Смежные вопросы