1

I'm currently implementing a SignalR application to send a message to several clients when an external library I've written fire an event.

I want to attach a unique handler to my event for every instance of my hub, so I could send the messages only once when it is fired; but as SignalR instanciate many hubs on every request, I end up with more than one event handler attached every time. So my question is: what can I do to attach only once on my event ?

Here is my code:

public class MyHub : Hub
{
    private static ExternalClass staticObject = new ExternalClass();

    public MyHub()
    {
        staticObject.MyEvent += staticObject_MyEvent;
    }

    private void staticObject_MyEvent(object sender, EventArgs e)
    {
        //Some irrelevant code which send messages to clients
    }
}

I know my question is pretty the same than this one and a lot of others, but I never found a satisfying anwser for multi-threaded or multi-instance environment - which is definitly my case.

Community
  • 1
  • 1
gobes
  • 507
  • 7
  • 25
  • if there are many hubs and you want one listener, maybe it shouldn't be the hubs that should listen to the event? Just a thought. – default Apr 17 '15 at 13:32

2 Answers2

0

Here is the code replacing my old event declaration in my library :

private bool isEventAlreadyRegistered = false;
private static readonly object verrou = new object();

private System.EventHandler myEvent = delegate { };
public event System.EventHandler MyEvent
{
    add
    {
        if(!isEventAlreadyRegistered)
        {
            lock(verrou)
            {
                //Double check as multiple add can be made simultaneously
                if(!isEventAlreadyRegistered)
                {
                    isEventAlreadyRegistered = true;
                    myEvent += value;
                }
            }
        }
    }
    remove
    {
        myEvent -= value;
    }
}

It works magnificently. My only doubt was about the performances with the lock; but as it is used only on the first call, it's negligible.

Of course, this solution only works when you have access to the source code of your event.

gobes
  • 507
  • 7
  • 25
  • 2
    In my opinion this is not a good solution. Simply because an other developer who wants to subscribe to this event dont know the internals. Maybe in his case it makes perfect sense to have multiple handlers bound to that event. – Andre Apr 17 '15 at 13:28
  • I wonder how it can work - as it is shown now, the event will not be registered at all. – JeffRSon Apr 17 '15 at 13:34
  • Should'nt `rankingOnUpdated` actually become `myEvent`? – JeffRSon Apr 17 '15 at 13:39
  • @Andre as I said in the question, I want to attach a unique handler to my event for every instance of my hub. Anyway, this snippet can be inside a wrapper set over the event. But if you have another proposition for my problem, I just want to improve my code :) – gobes Apr 17 '15 at 13:43
0

Hubs live in transient life. Meaning it will be created for each type of transaction (connected, on client message, dissconnected etc).

Never, ever have anything else then SignalR logic in the hub. Move your code somewhere else and invoke the client method when you want to upate. Or use a library that already have abstracted that for your. For example this library (I'm the author)

https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/wiki

Live demo: http://malmgrens.org/signalR/

Anders
  • 17,306
  • 10
  • 76
  • 144