SignalR通知系统

mit*_*daa 2 c# signalr

这是我第一次玩SignalR.我想建立一个通知系统,其中定期服务器检查,看看是否有什么(查询数据库)来播放,如果有那么它广播到所有的客户.我碰到这个职位#2,想知道是否修改代码以使DB调用在一个特定的时间间隔确实是这样做的正确方法.如果不是,有更好的方法吗?

我确实在这里发布了许多与通知相关的问题,但没有任何代码.因此这篇文章.

这是我正在使用的确切代码:

public class NotificationHub : Hub
{
    public void Start()
    {
        Thread thread = new Thread(Notify);
        thread.Start();
    }

    public void Notify()
    {
        List<CDCNotification> notifications = new List<CDCNotification>();
        while (true)
        {
            notifications.Clear();
            notifications.Add(new CDCNotification() 
                { 
                    Server = "Server A", Application = "Some App", 
                    Message = "This is a long ass message and amesaadfasd asdf message", 
                    ImgURL = "../Content/Images/accept-icon.png" 
                });
            Clients.shownotification(notifications);
            Thread.Sleep(20000);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经看到一些奇怪的行为,其中通知比他们应该更频繁.即使我应该每隔20秒就能得到它,我会在4-5秒左右得到它并且我收到多条消息.这是我的客户:

var notifier = $.connection.notificationHub;
notifier.shownotification = function (data) {
    $.each(data, function (i, sample) {
        var output = Mustache.render("<img class='pull-left' src='{{ImgURL}}'/> <div><strong>{{Application}}</strong></div><em>{{Server}}</em> <p>{{Message}}</p>", sample);
        $.sticky(output);
    });
};

$.connection.hub.start(function () { notifier.start(); });
Run Code Online (Sandbox Code Playgroud)

ntz*_*lis 6

几个笔记:

  1. 只要第二个客户端连接到您的服务器,就会有2个线程发送通知,因此如果您有多个客户端,则间隔小于20秒
  2. 在ASP.NET中手动处理线程被认为是不好的做法,如果可能的话应该避免这种情况
  3. 一般来说,这有点像polling一样,这是SignalR让你摆脱的东西,因为你不需要发信号通知服务器/客户端

为了解决这个问题,你需要这样的东西(再次,Web应用程序中的线程通常不是一个好主意):

public class NotificationHub : Hub
{
  public static bool initialized = false;
  public static object initLock = new object();

  public void Start()
  {
    if(initialized)
      return;

    lock(initLock)
    {
      if(initialized)
        return;

      Thread thread = new Thread(Notify);
      thread.Start();

      initialized = true;
    }
  }

  public void Notify()
  {
    List<CDCNotification> notifications = new List<CDCNotification>();
    while (true)
    {
      notifications.Clear();
      notifications.Add(new CDCNotification() { Server = "Server A", Application = "Some App", Message = "This is a long ass message and amesaadfasd asdf message", ImgURL = "../Content/Images/accept-icon.png" });
      Clients.shownotification(notifications);
      Thread.Sleep(20000);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

静态初始化的标志可防止多个线程被创建.围绕它的锁定是为了确保标志仅设置一次.