1

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

4

2 に答える 2

4

実際には 2 つの newPublication イベントがあるようです。1 つはサブスクライバーに、もう 1 つはパブリッシャーにあります。パブリッシャーで 1 つを作成していますが、サブスクライバーは自分のイベントのみをサブスクライブします。

Subscriber クラスがどのように機能するかは次のとおりです。

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 のイベント モデル (これもメモリ リークがない) に慣れておくことをお勧めします。

于 2011-02-06T10:00:51.187 に答える
1

2 つの異なるイベントを宣言しました。パブリッシャー インスタンスとサブスクライバー インスタンスは、まったく接続されていません。したがって、パブリッシャーでイベントを発生させても、サブスクライバーのハンドラーはトリガーされません。

あなたがする必要があるのは概略です:

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

これらのクラスのインスタンス化と への呼び出しの間にこのコードを配置しますAddNews()

更新:newPublicationしたがって、クラス内の宣言Subscriberはまったく役に立たないため、そのクラスから削除する必要があります。必要に応じて、PublisherインスタンスをSubscriberのコンストラクタに渡して、 内でイベントを関連付けることができますSubscriber。ただし、一般的には、イベント パブリッシャーとイベント サブスクライバーの両方の外にイベント ワイヤリング コードを保持することをお勧めします。

于 2011-02-06T09:58:01.143 に答える