3

I am having a very strange behaviour as in this picture:

enter image description here

As you can see in the Watch window, everything that can be possibly null are not null.

Here is the full code of the function:

    public LogInTokenCache GetUserIdFromToken(string token)
    {
        LogInTokenCache item = null;

        if (this.TokenCache.ContainsKey(token))
        {
            item = this.TokenCache[token];

            if (item.ExpirationTime < DateTime.Now)
            {
                this.TokenCache.Remove(item.Token);
                return null;
            }
        }
        else
        {
            LogInTokenBusiness tokenBusiness = new LogInTokenBusiness();

            var entity = tokenBusiness.FindToken(token);
            if (entity != null && entity.Token != null)
            {
                item = new LogInTokenCache()
                {
                    Token = entity.Token,
                    UserID = entity.UserId,
                    ExpirationTime = entity.ExpirationTime,
                };

                this.TokenCache.Add(item.Token, item);
            }
        }

        return item;
    }

I used Find All References feature, and this is the only where I use the Constructor as well as a declaration (I use it for entire Web App):

public class IdentityController : Controller
{

    private static EmailAdpater EmailAdapter = new EmailAdpater();
    private static UserIdentityTokenShortener TokenShortener = new UserIdentityTokenShortener();
    public static LoginTokenManager LoginTokenManager = new LoginTokenManager();
    ...

Has anyone encountered this problem? What did I do wrong?

EDIT: Added StackTrace and Details EDIT2: Edited title so future people can search this topic in case they have the same problem.

enter image description here

   at System.Collections.Generic.Dictionary12.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary12.Add(TKey key, TValue value)
   at MobileDatingAPI.Models.LoginTokenManager.GetUserIdFromToken(String token) in d:\FPT University\Capstone 2\TFSRepo\Projects\MobileDatingAPI\MobileDatingAPI\Models\LoginTokenManager.cs:line 48
   at MobileDatingAPI.Models.Utils.GetUserFromTokenID(Controller controller, String token, BaseApiViewModels model) in d:\FPT University\Capstone 2\TFSRepo\Projects\MobileDatingAPI\MobileDatingAPI\Models\Utils\Utils.cs:line 68
   at MobileDatingAPI.Controllers.CommunityController.UpdateActivity(String token, Nullable11 longitude, Nullable11 latitude) in d:\FPTUniversity\Capstone 2\TFSRepo\Projects\MobileDatingAPI\MobileDatingAPI\Controllers\CommunityController.cs:line 84
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary12 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary12 parameters)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.ActionInvocation.InvokeSynchronousActionMethod()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult12.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
   at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f()
Luke Vo
  • 12,823
  • 19
  • 79
  • 132
  • 5
    Click "View Detail", post the full stack trace. – CodeCaster Mar 06 '15 at 10:39
  • 2
    And... do you use multi-threading? – Patrick Hofman Mar 06 '15 at 10:40
  • 1
    We can't reproduce it with this code. – Patrick Hofman Mar 06 '15 at 10:40
  • I was also thinking 'check the stack trace' but this sounds like a job for intellitrace. –  Mar 06 '15 at 10:43
  • There is a lot of `Async` in your call stack. I suppose that is the issue. Hoe do you initialize the `TokenCache` dictionary? – Patrick Hofman Mar 06 '15 at 10:46
  • Hello, thank you for quick reply, I added the StackTrace and Details. I also checked the IntelliTrace before asking, but it didn't provide any useful information. And Yes, I use Multi-Threading, but what could possibly cause the problem? – Luke Vo Mar 06 '15 at 10:46
  • @PatrickHofman I posted the entire class. I intialize it in the constructor, is it possible to call a method even before it is instantiated? – Luke Vo Mar 06 '15 at 10:47
  • Check for this and add to dictionary if(item != null) – Lokesh B R Mar 06 '15 at 10:48
  • How do you instantiate and assign the `LoginTokenManager`? To be clear, the exception is thrown from the `private void Insert(TKey key, TValue value, bool add)` of the `Dictionary` type, which means it's your code doing something wrong. Please show all relevant code. – CodeCaster Mar 06 '15 at 10:49
  • @CodeCaster I declared a static variable. (I added the code to the question). – Luke Vo Mar 06 '15 at 10:52
  • This is definitely not a duplicate of the "how to deal with NullPointerException" question. – Sergey Kalinichenko Mar 06 '15 at 10:53
  • @DatVM: `static` is a big NONO in any web app. Get rid of them. – leppie Mar 06 '15 at 10:55
  • @leppie Thank you for your advice. Can you please give reference to the reason and/or the alternatives? – Luke Vo Mar 06 '15 at 10:59
  • 1
    @DatVM: You will run into concurrency issues 9 out of 10 times. Go with the answer and use `ConcurrentDictionary` and be careful about any other members in that class. It could also have concurrency issues. – leppie Mar 06 '15 at 11:08

2 Answers2

8

I use Multi-Threading

This is almost certainly the problem then: since everything in your code is null-checked and/or created with values that are non-null, the only place where the problem could happen is the implementation of Dictionary.

When the capacity of the dictionary is reached, the collection re-allocates its internal data structures. If one thread catches the dictionary in the middle of reallocation performed by another thread, some of the variables inside the buckets would be uninitialized, i.e. null or default, depending on the type. Since this is not a usual state for a bucket, the dictionary will try to dereference it, causing null pointer exception.

In order to avoid this problem, add synchronization around the call of Add:

// Add this declaration where you declare TokenCache dictionary
object TokenCacheLock = new object();
...
lock (TokenCacheLock) {
    // Add a lock around your access of TokenCache
    if (this.TokenCache.ContainsKey(token)) ...
}

Note that since additions to the dictionary happen concurrently with reads, all accesses to TokenCache need to be synchronized.

A much simpler solution would be using ConcurrentDictionary<K,V>.

Sergey Kalinichenko
  • 675,664
  • 71
  • 998
  • 1,399
  • Thank you very much, nice to know. I will also edit the title for future people who get the problem can search this topic. – Luke Vo Mar 06 '15 at 11:19
0
    public static LoginTokenManager LoginTokenManager = new LoginTokenManager();

(I use it for entire Web App):

There's your problem. The Dictionary<TKey, TValue> type is not thread-safe. See Thread safety with Dictionary<int,int> in .Net.

Community
  • 1
  • 1
CodeCaster
  • 131,656
  • 19
  • 190
  • 236