为什么我的C#自定义事件没有被提出?

时间:2011-02-06 09:54:28

标签: c# .net events event-handling custom-event

这不是我第一次在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 个答案:

答案 0 :(得分:4)

看来你实际上有2个新的出版事件:一个在订阅者中,一个在发布者中。你正在发布一个发布者,但订阅者只订阅他们自己的活动。

以下是订阅者类的工作方式:

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);
}

为了便于使用,您可能希望向Publisher类引入一个Subscribe方法,如下所示:

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

请注意,附加但从未分离并且可能导致.NET应用程序中的内存泄漏的事件处理程序。当不再需要时,总是使用 - =运算符分离事件处理程序(例如,在WinForms应用程序中,我通常在触发FormClosed事件时分离事件处理程序以获取控件事件)。 Here是一篇很好的文章,深入解释了它,here是另一个展示内存泄漏检测的文章。

对于高级事件概念,您可能希望熟悉F#和Reactive Framework的事件模型(也没有内存泄漏),如this系列文章中所述。

答案 1 :(得分:1)

您已宣布两个不同的事件。您的发布商实例和订阅者实例以任何方式连接。因此,在发布者中引发事件不会触发订阅者中的处理程序。

您需要做的是示意性的:

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

将此代码放在这些类的实例化之间,并调用AddNews()

更新:因此,newPublication类中Subscriber的声明完全没用,应从该类中删除。如果需要,可以将Publisher实例传递给Subscriber的构造函数,以便在Subscriber内进行事件连接。但是,将事件接线代码保留在事件发布者和事件订阅者之外通常是个好主意。