SIgnalR-不使用单一模式

时间:2014-05-28 16:23:04

标签: c# singleton signalr

在我的应用程序中,我根据他的订阅向每个人发送实时更新。所以例如如果客户被描述为项目1,2& 3他应该只看到这些项目的更新,而同时如果另一个客户订阅了项目4,5& 6然后他应该能够收到这些项目的实时更新。我的问题是,一旦我连接第二个id信号器忘记了旧组,只开始新ID的通知。我想是的,因为只有一个实时更新实例正在运行,并且它在所有连接的客户端之间共享。有没有办法让每个连接的客户端拥有它自己的实时对象实例?

 public class DataHub : Hub
{
    private readonly RealTimeData data;

    public DataHub() : this(RealTimeData.Instance) { }

    public DataHub(RealTimeData rdata)
    {
        data = rdata; //can I intsantiate RealTimeData object here?
    }

    public void Start(Int64 routerId)
    {
        data.StartTimer(routerId);
    }
 }

 public class RealTimeData
 {
     private readonly static Lazy<RealTimeData> _instance = new Lazy<RealTimeData>(() => new RealTimeData(GlobalHost.ConnectionManager.GetHubContext<DataHub>().Clients));  //will avoiding this create a separate instance for each client? 
 private IHubConnectionContext Clients;

    public Timer timer;
    private readonly int updateInterval = 1000;
    private readonly object updateRecievedDataLock = new object();
    private bool updateReceivedData = false;
    List<Items> allItems = new List<Items>();
    private RealTimeData()
    {
    }

    private RealTimeData(IHubConnectionContext clients)
    {
        Clients = clients;          
    }

    public static RealTimeData Instance
    {
        get
        {
            return _instance.Value;
        }
    }
     public void StartTimer(Int64 routerId)
    {
        this.routerId = routerId;
        timer = new Timer(GetDataForAllItems, null, updateInterval, updateInterval);       
    }
      public void GetDataForAllItems(object state)
    {
        if (updateReceivedData)
        {
            return;
        }
        lock (updateRecievedDataLock)
        {
            if (!updateReceivedData)
            {
                updateReceivedData = true;
                //get data from database
                allItems = Mapper.Instance.GetDataForAllItems(routerId);
                updateReceivedData = false;
                //send it to the browser for update
                BroadcastData(allItems);
            }
        }
    }


 }

2 个答案:

答案 0 :(得分:1)

我认为你是从一个错误的角度攻击这个问题。而不是每秒轮询数据库,而是保存到数据库的操作会在您转发给客户端的消息总线上发布消息。

看看这个图书馆,

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

演示项目 https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/tree/master/SignalR.EventAggregatorProxy.Demo.MVC4

免责声明:我是图书馆的作者

答案 1 :(得分:1)

SignalR v2中的群组订阅是使用Hub&gt;中的this.Groups.Addthis.Groups.Remove方法处理的。 HubBase祖先类。

通过使用类似的方法,可以使用这些方法订阅示例中的1,2,3或4,5,6组。

public class DataHub : Hub
{
    public async Task Register(int groupNumber)
    {
        await this.Groups.Add(this.Context.ConnectionId, groupNumber.ToString());
    }

    public async Task Unregister(int groupNumber)
    {
        await this.Groups.Remove(this.Context.ConnectionId, groupNumber.ToString());
    }
}

在客户端上,可以通过将组号传递给Register / Unregister方法来调用它。一个例子可能是:

this._DataHub.Invoke("Register", "1");

从您发布更新的RealTimeData单例或其他业务类,您将引用GlobalHost.ConnectionManager.GetHubContext<DataHub>()并调用然后使用.Clients.Group("1").<clientMethod>来调用客户端方法。

例如:

var hubContext = GlobalHost.ConnectionManager.GetHubContext<DataHub>();
hubContext.Clients.Group("1").UpdateDisplay("New tweet");

要阅读更多内容,请查看http://www.asp.net/signalr/overview

我希望这能回答这个问题。