0

Good evening,

In my SignalR application I have a javascript timer that is ran for all users "simultaneously". At the end of this timer, a server function is called, and this is where this problem starts. As the function is called at the end of the timer, every connected user calls it at the same time, which is unnecessary because it will return the same output for all connected users. Being a logically complex function, having the server run it unnecessarily for all users adds up to be a great resource waste.

How can I make it so that it is ran only once (maybe the first time it is called (until the next timer stops))?

Thank you in advance

Tiago
  • 347
  • 1
  • 3
  • 12
  • 1
    You could use a static bool variable to keep track of this. Default the variable to false and set it to true on first execution. Ignore the execution if this bool is set to true for future executions. Or persist a flag in a db which you set and check against with the same logic described above. – Jako Basson Mar 01 '19 at 21:27
  • @JakoBasson thank you. I considered the database solution but thought it would be a waste of resources (not sure if making all these requests just to know the state like this would make a difference in real world scenario). The static variable sounds like what I was looking for, but in all honesty, I am not really familiar with these state variables, is it a variable declared in the class as static? – Tiago Mar 01 '19 at 21:39
  • 1
    is it a variable declared in the class as static? Yes. Here's a link which might help you: https://stackoverflow.com/questions/14154892/scope-of-static-variable-in-multi-user-asp-net-web-application – Jako Basson Mar 01 '19 at 21:43
  • @JakoBasson thanks a lot. this solves a lot of problems. I don't even know how I could be ignorant to such a simple aspect – Tiago Mar 01 '19 at 21:50

1 Answers1

0

You could make use of GlobalHost.ConnectionManager.GetHubContext. This will allow you to get any hub context and then trigger Clients.All.YourFunction on that context. That will send send a message to all connected clients subscribed to that hub.

You will need to have a background process that runs every at the time your JavaScript function fires (by the way, relying on all your clients to call a JavaScript function simultaneously is really not a good idea; different client locations and different machine performance will mean they're not likely to be simultaneous).

The following is assuming that you're just running this on a single server. If you're going to be deploying this to a web farm, then you'll need to use a Database value to ensure you don't repeat the same work, or set up a particular server instance to be responsible for doing the calls (otherwise you'll end up with one call per server).

Create a process that runs in the Background (I'm sticking with a simple thread here, I actually use HangFire for this, but this will suffice for the example), e.g. On App_Start

Thread thread = new Thread(new ThreadStart(YourFunction));
thread.Start();

Then create YourFunction which will be responsible for your client calls:

private bool Cancel = false;

private void YourFunction()
{
    do 
    {
        string foo = "Foo";

        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<YourHub>();
        context.Clients.All.SendYourMessage(foo);

        Thread.Sleep(10000);
    } 
    while(!Cancel)
}

And then on the client, just handle the message from the hub:

youyHub.client.sendYourMessage = function(message)
{
   // message == "Foo"
};
djdd87
  • 67,346
  • 27
  • 156
  • 195
  • *this sounds like a solution. although I already fixed the problem by it's root, using static variables to create a server timer (that starts at the same time as the javascript one displayed to the users) and then having the server call it when the timer ends, thus the function being called only once – Tiago Mar 03 '19 at 17:57