Почему мое пользовательское событие в C # не вызывается? - PullRequest
1 голос
/ 06 февраля 2011

Я не первый раз создаю пользовательское событие в C #.Мне непонятно, почему это не работает в этом простом случае.

У меня есть издатель с подписчиками.В моей основной программе я создал 1 издателя и 2 подписчика.Когда вызывается addNews, подписчики должны получить событие NewPublication:

static void Main()
{
    Publisher publisher = new Publisher();
    Subscriber subscriber1 = new Subscriber("John");
    Subscriber subscriber2 = new Subscriber("Jane");

    publisher.AddNews("custom event NewPublication");   
}

В subscriber.cs У меня есть:

public delegate void NewPublication(Publisher fromPublisher, String Message);

public class Publisher {

    private List<String> newsList = new List<String>();
    public event NewPublication newPublication;

    public void AddNews(String news) {
        newsList.Add(news);

        if (newPublication != null)
        {
            newPublication(this, news);
        }
    }
}

В подписчике у меня есть:

private String m_Name;
private event NewPublication newPublication;


public Subscriber(String name) {
    m_Name = name;
    newPublication += new NewPublication(subscriber_newPublication);
}

public void subscriber_newPublication(Publisher fromPublisher, String Message) {
    MessageBox.Show(m_Name + " is notified for " + Message);
}

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

Что действительно отличается от примера кода MSDN: http://msdn.microsoft.com/en-us/library/w369ty8x.aspx

Ответы [ 2 ]

4 голосов
/ 06 февраля 2011

Похоже, что на самом деле у вас есть 2 события newPublication: одно в подписчике и одно в издателе. Вы поднимаете один в Publisher, но подписчики подписываются только на собственное событие.

Вот как должен работать ваш класс подписчика:

private String m_Name;
private Publisher m_Publisher;

public Subscriber(String name, Publisher publisher) {
     m_Name = name;
     m_Publisher = publisher;
     m_Publisher.newPublication += new NewPublication(subscriber_newPublication);
}

public void subscriber_newPublication(Publisher fromPublisher, String Message) {
    MessageBox.Show(m_Name + " is notified for " + Message);
}

Для простоты использования вы можете захотеть ввести метод Subscribe для вашего класса Publisher, например так:

public Subscriber Subscribe(String name)
{
     return new Subscriber(name, this);
}

Обратите внимание, что обработчики событий, которые присоединены, но никогда не отсоединяются, могут вызвать утечки памяти в вашем приложении .NET. Всегда используйте оператор - = для отсоединения обработчиков событий, когда они вам больше не нужны (например, в приложении WinForms я обычно отсоединяю обработчики событий для событий управления, когда происходит событие FormClosed). Здесь - хорошая статья, которая подробно объясняет это, а здесь - еще одна статья, которая демонстрирует обнаружение утечек памяти.

Для расширенной концепции событий вы можете ознакомиться с F # и моделью событий Reactive Framework (которые также не имеют утечек памяти), как описано в этой серии статей .

1 голос
/ 06 февраля 2011

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

То, что вам нужно сделать, это схематично:

publisher.newPublication += subscriber1.subscriber_newPublication;
publisher.newPublication += subscriber2.subscriber_newPublication;

Поместите этот код между экземплярами этих классов и вызовами AddNews().

Обновление: Следовательно, объявление newPublication в классе Subscriber совершенно бесполезно и должно быть удалено из этого класса.Если вам нужно, вы можете передать экземпляр Publisher в конструктор Subscriber, чтобы связать событие в Subscriber.Однако, как правило, рекомендуется хранить код подключения к событиям как для издателей, так и для подписчиков.

...