Question

This is my first time playing around with SignalR. I am trying to build a notification system where the server checks at regular intervals to see if there is something (query database) to broadcast and if there is then it broadcasts it to all the clients. I came across this post on Stackoverflow and was wondering if modifying the code to make a DB call at a particular interval was indeed the right way to do it. If not is there a better way to do it?

I did see a lot of Notification related questions posted here but none with any code in it. Hence this post.

This is the exact code that I am using:

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

I am already seeing some weird behaviour where the notifications come more often than they are supposed to. Even though I am supposed to get it every 20s I get it around 4-5 secs and I get multiple messages. Here is my client:

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(); });
Was it helpful?

Solution

Couple of notes:

  1. As soon as a second client connects to your server there will be 2 threads sending the notifications, therefore if you ave more than one client you will have intervals smaller than 20s
  2. Handling thread manually within ASP.NET is considered bad practice, you should avoid this if possible
  3. In general this smells a lot like polling which is kind of the thing SignalR lets you get rid of since you don't need to signal the server/client

In order to solve this you need todo something like this (again, threads in a web application are generally not a good idea):

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

The static initialized flag prevents multiple threads from being created. The locking around it is to ensure that the flag is only set once.

OTHER TIPS

I am working on the same task over here. Instead of continuously checking the database, I created my own events and listener, where an event is RAISED when a NOTIFICATION IS ADDED :) What do you think about that?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top