在多线程环境中仅订阅一次事件

时间:2015-04-17 13:21:09

标签: c# events signalr

我正在实现一个SignalR应用程序,当我写一个外部库时,我会向几个客户端发送消息。

我想为我的集群的每个实例附加一个唯一的处理程序,所以我只能在它被触发时发送一次消息;但是由于SignalR在每个请求上实现了许多集线器,我最终每次都附加了多个事件处理程序。所以我的问题是:在活动中我只能做一次附加一次吗?

这是我的代码:

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

我知道我的问题与this one以及其他许多问题完全相同,但我从未在多线程或多实例环境中找到令人满意的答案 - 这绝对是我的理由。

2 个答案:

答案 0 :(得分:0)

以下代码替换了我的库中的旧事件声明:

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

它的作品非常棒。我唯一的疑问是关于锁的表现;但由于它仅在第一次通话时使用,因此可以忽略不计。

当然,此解决方案仅在您有权访问活动的源代码时才有效。

答案 1 :(得分:0)

枢纽生活在短暂的生活中。这意味着它将为每种类型的事务创建(连接,客户端消息,无连接等)。

永远不会在集线器中有任何其他信号逻辑。将代码移动到其他位置,并在想要更新时调用客户端方法。或者使用已经抽象出来的库。例如这个图书馆(我是作者)

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

现场演示: http://malmgrens.org/signalR/