C# 在多线程环境中只订阅一次事件

C# 在多线程环境中只订阅一次事件,c#,events,signalr,C#,Events,Signalr,我目前正在实现一个信号器应用程序,以便在我编写的外部库触发事件时向多个客户端发送消息 我想为我的集线器的每个实例为我的事件附加一个唯一的处理程序,这样当它被触发时,我只能发送一次消息;但由于signar在每个请求上实例化了许多集线器,因此每次都会附加多个事件处理程序。所以我的问题是:我该怎么做才能在我的活动中只附加一次 这是我的密码: public class MyHub : Hub { private static ExternalClass staticObject = new Ex

我目前正在实现一个信号器应用程序,以便在我编写的外部库触发事件时向多个客户端发送消息

我想为我的集线器的每个实例为我的事件附加一个唯一的处理程序,这样当它被触发时,我只能发送一次消息;但由于signar在每个请求上实例化了许多集线器,因此每次都会附加多个事件处理程序。所以我的问题是:我该怎么做才能在我的活动中只附加一次

这是我的密码:

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

我知道我的问题与其他许多问题非常相似,但我从未找到一个适合多线程或多实例环境的令人满意的anwser,这就是我的情况。

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

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;
    }
}
它工作得非常出色。我唯一的怀疑是锁的性能;但由于它只在第一次通话时使用,因此可以忽略不计


当然,这个解决方案只有在您有权访问事件的源代码时才有效。

集线器生活在短暂的生活中。这意味着它将为连接的每种类型的交易、客户端消息、Disconnected等创建

在集线器中从来没有信号逻辑以外的任何东西。将代码移到其他地方,并在需要升级时调用客户机方法。或者使用一个已经为您的应用程序抽象了它的库。例如,我是这个图书馆的作者

现场演示:

我认为这不是一个好的解决方案。只是因为其他想要订阅此事件的开发人员不知道其内部结构。也许在他的情况下,将多个处理程序绑定到该事件是非常有意义的。我想知道它是如何工作的——正如现在所示,该事件根本不会被注册。rankingOnUpdated是否真的应该成为myEvent?@Andre正如我在问题中所说的,我想为我的中心的每个实例为我的事件附加一个唯一的处理程序。无论如何,此代码段可以位于事件的包装器集中。但是,如果您对我的问题有另一个建议,我只想改进我的代码:如果有许多中心,而您需要一个侦听器,那么可能不应该由中心来侦听事件?只是一个想法。