Ravi Sanker
Ravi Sanker

Reputation: 84

Using an event handler with a singleton c#. EventHandler is null

I have a singleton class and an eventHandler sendResponse. I want to perform some operation in a subscriber class when the publisher raises the event.

public class Publisher
{
    private static Publisher instance;
    public event EventHandler SendResponse;

    public static Publisher Instance
    {
        get
        {
            if (instance == null)
                instance = new Publisher();
            return instance;
        }
    }

    public void Send()
    {
        this.SendResponse(instance, EventArgs.Empty);
    }
}

In the subscriber, I say

public string performSomething()
{
       Publisher copy = Publisher.Instance;
       copy.SendResponse += new EventHandler(copy_SendResponse);
       bool isCompleted = false;

       // Start an async task method which is in another class and is the publisher.

       while(isCompleted != true);
       return "Success";
}

//Define the function copy_SendResponse.
public void copy_SendResponse()
{
      isCompleted = true;
}

The code with the subscriber gets executed first. But SendResponse is not bound to anything when i call the Send() method in the publisher. In the publisher i am using

 // when async task completes
 Publisher copy = Publisher.Instance;
 copy.Send();
 // end of function

On debugging, SendResponse is actually null when i say copy.Send(). It throws an error "Object reference not set to an instance of an object."

Upvotes: 1

Views: 2977

Answers (1)

BendEg
BendEg

Reputation: 21098

At first i would delcare singleton always like this: private static Publisher instance = new Publisher();, in my point of view this is clearer than in the getter. Second, always proof whether your event is subscripted:

private void Send()
{
    if (this.SendResponse != null)
    {
        this.SendResponse(this, EventArgs.Empty); // <<-- pass this
    }
}

If you want to be sure, that no one else can make an instance of the singleton class, make it's constructor private. Rather pass this instead of instance, to be sure your passing the correct object as sender.

If you follow all rules, your code should work. I can not see any other problem with the amount of your information/code.

EDIT

Working example:

public class Publisher
{
    // Instance
    private static readonly Publisher instance = new Publisher();
    public event EventHandler SendResponse;

    public static Publisher Instance
    {
        get
        {
            return instance;
        }
    }

    /// <summary>
    /// Private constructor
    /// </summary>
    private Publisher()
    {

    }

    public void Send()
    {
        // proof if subscipted
        if (this.SendResponse != null)
        {
            // Pass this
            this.SendResponse(this, EventArgs.Empty);
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var copy = Publisher.Instance;
        copy.SendResponse += Copy_SendResponse;

        var copy2 = Publisher.Instance;
        copy2.Send();

        Console.ReadLine();
    }

    /// <summary>
    /// Event
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private static void Copy_SendResponse(object sender, EventArgs e)
    {
        Console.WriteLine("It works!");
    }
}

Upvotes: 2

Related Questions