0

I am implementing COMET in my MVC web application by using the PokiIn library for pushing notifications to clients.

Whenever a client connects, the ClientId is available in the OnClientConnected event of the CometWorker class:

public static Dictionary<int, string> clientsList 
                            = new Dictionary<int, string>();
public static string clientId = "";
static void OnClientConnected(string clientId, 
                                        ref Dictionary<string, object> list)
{
        BaseController.clientId = clientId;
}

I assign the the clientId received in the handler to the static ClientId of controller. And then when the Handler action is called, I map this ClientId to the Identity of the logged in user:-

public ActionResult Handler()
        {
            if (User.Identity.IsAuthenticated)
            {
                if (clientsList.Keys.Contains(currentUser.UserId))
                    clientsList[currentUser.UserId] = clientId;
                else
                    clientsList.Add(currentUser.UserId, clientId);
            }
            return View();
        }

Because multiple requests will be served by different threads on the server, each will access the static ClientId in both the methods.

How can I synchronize its access, so that untill one request is done with it in both the methods (OnClientConnected and Handler), the other request waits for it ?

Please tell me if my question is not clear. I will try to improve it further.

teenup
  • 7,459
  • 13
  • 63
  • 122
  • possible duplicate of [How can I lock a private static field of a class in one static method and then release it in some other instance method ?](http://stackoverflow.com/questions/5441657/how-can-i-lock-a-private-static-field-of-a-class-in-one-static-method-and-then-re) – Darin Dimitrov Mar 26 '11 at 13:38

2 Answers2

2

Store the clientid in the user's session not in a static variable on the controller. It needs to be in data associated with the user not the entire application. Or better yet, resolve the name/id lookup when the client connects.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • I can not access the User's Session in the static OnClientConnected event, thats why I am assigning to static field and then using it in the Action Method. – teenup Mar 26 '11 at 13:08
  • @Puneet - not even through HttpContext.Current? It should be available since the "event" is obviously associated with a request. – tvanfosson Mar 26 '11 at 13:11
  • No, I can not access HttpContext.Current, and I think its correct too, because static methods cannot access instance methods, and Current is associated with an instance. I need a way to lock the ClientId in the first event method and hold the lock till the second Handler method executes and maps the ClientId to UserId. Till then others should wait. – teenup Mar 26 '11 at 13:16
  • 1
    @Puneet - First, HttpContext.Current is a static object that exists for each request so it should be available. You're probably thinking of the HttpContext instance variable on the controller. They're not the same thing. Second, I get that you probably need to keep some static list of clients around since you'll be pushing to them without them having made a request, but holding the id over two request cycles is probably not the way to go. I'd suggest looking into accessing the current HttpContext and resolving the name/id at the time of connection. As @Wahid indicates locking is required. – tvanfosson Mar 26 '11 at 13:28
0

I think you should use lock(clientsList){} whenever you want to update your dictionary

Wahid Bitar
  • 13,776
  • 13
  • 78
  • 106
  • You should never lock on a public object because other parts of your code could do the same. See: http://stackoverflow.com/questions/251391/why-is-lockthis-bad – Ade Miller Mar 26 '11 at 17:52