.NET Multithreaded Access to Shared Login Session .NET Multithreaded Access to Shared Login Session multithreading multithreading

.NET Multithreaded Access to Shared Login Session


It's an unusual problem, and I'm not aware of anything built in that specifically addresses this.

Bearing in mind that I've knocked this up in a few minutes, and so I'd definitely advise not using this until plenty of people have had a chance to look at it and point out its flaws, this is what I thought of:

private Task _loginLock = null;public void DoLoggedInCheck(){    if (!Api.IsLoggedIn)    {        var tcs = new TaskCompletionSource<int>();        var tsk = tcs.Task;        var result = Interlocked.CompareExchange(ref _loginLock, tsk, null);        if (result == null)        {            if (!Api.IsLoggedIn)            {                Api.Login();            }            Interlocked.Exchange(ref _loginLock, null);            tcs.SetResult(1);        }        else        {            result.Wait();        }    }}

The logic being that, out of all of the threads that spot that a login is required, they all compete (via the CompareExchange) to be the one to volunteer to fix the problem. One of them wins and does the task, the remainder just wait for the winner to signal their success.

There's still a small amount of raciness here, but it should be rare.


If you want to resolve it only using worker threads I don't see any other ways, there is a critical section and this is nature of critical section that only 1 thread can pass it at a time. Completely other approach would be do delegate handling of critical section to separate thread. I am not sure that it will be more performant (most probably it will be much slower) but once Api is logged in there will be no traffic jam.

        private static AutoResetEvent requestLogin = new AutoResetEvent();        private static ManualResetEvent responseLogin = new ManualResetEvent();        //Worker thread:        if(!Api.IsLoggedIn)         {            requestLogin.Set();            responseLogin.WaitOne();        }        //Login thread        requestLogin.WaitOne();        if(!Api.IsLoggedIn)        {            Api.Login();        }        responseLogin.Set();