C# 在异步上下文中添加到字典时出现NullReferenceException

C# 在异步上下文中添加到字典时出现NullReferenceException,c#,.net,dictionary,asp.net-mvc-5,nullreferenceexception,C#,.net,Dictionary,Asp.net Mvc 5,Nullreferenceexception,我有一种非常奇怪的行为,如图所示: 正如您在“监视”窗口中看到的,所有可能为null的内容都不是null 以下是该函数的完整代码: public LogInTokenCache GetUserIdFromToken(string token) { LogInTokenCache item = null; if (this.TokenCache.ContainsKey(token)) { item = th

我有一种非常奇怪的行为,如图所示:

正如您在“监视”窗口中看到的,所有可能为
null
的内容都不是
null

以下是该函数的完整代码:

    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;
    }
有人遇到过这个问题吗?我做错了什么

编辑:添加StackTrace和详细信息 编辑2:编辑标题,以便未来的人可以搜索此主题,以防他们有相同的问题

   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()

at System.Collections.Generic.Dictionary12.Insert(TKey-key,TValue-value,Boolean-add)
在System.Collections.Generic.Dictionary12.Add(TKey键,TValue值)
位于d:\FPT University\Capstone 2\TFSRepo\Projects\MobileDatingAPI\MobileDatingAPI\Models\LoginTokenManager.GetUserIdFromToken(字符串标记)中的MobileDatingAPI.Models.LoginTokenManager.GetUserIdFromToken(字符串标记):第48行
在d:\FPT University\Capstone 2\TFSRepo\Projects\MobileDatingAPI\MobileDatingAPI\Models\Utils.GetUserFromTokenID(控制器控制器、字符串令牌、BaseApiViewModels模型)中的MobileDatingAPI.Models.GetUserFromTokenID处:第68行
在d:\FPTUniversity\Capstone 2\TFSRepo\Projects\mobiledatangapi\Controllers\CommunityController.UpdateActivity(字符串标记,Nullable11经度,Nullable11纬度)中的MobiledatangAPI.Controllers.UpdateActivity(字符串标记,Nullable11经度,Nullable11纬度):第84行
在lambda_方法中(闭包、控制器基、对象[])
位于System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller,Object[]参数)
位于System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext ControllerContext,IDictionary12参数)
位于System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext ControllerContext、ActionDescriptor ActionDescriptor、IDictionary12参数)
在System.Web.Mvc.Async.AsyncControllerActionInvoker.ActionInvoke.InvokeSynchronousActionMethod()中
在System.Web.Mvc.Async.AsyncControllerActionInvoker.b_u39(IAsyncResult asyncResult,ActionInvokeInnerInvokeState)
位于System.Web.Mvc.Async.AsyncResultRapper.WrappedAsyncResult12.CallEndDelegate(IAsyncResult asyncResult)
位于System.Web.Mvc.Async.AsyncResultRapper.WrappedAsyncResultBase`1.End()
在System.Web.Mvc.Async.asyncResultRapper.End[TResult](IAsyncResult asyncResult,对象标记)
位于System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
在System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.b__3d()中
在System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.c__DisplayClass46.b__3f()中
我使用多线程

这几乎肯定就是问题所在:因为代码中的所有内容都是用非空值检查和/或创建的,所以问题可能发生的唯一地方是实现
字典

当达到字典的容量时,集合将重新分配其内部数据结构。如果一个线程在另一线程执行重新分配的中间捕获字典,则桶内的一些变量将不被初始化,即“代码>空NU/CODE >或默认,取决于类型。由于这不是bucket的常见状态,字典将尝试取消对它的引用,从而导致空指针异常

为了避免此问题,请在调用
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)) ...
}
请注意,由于字典的添加与读取同时发生,因此需要同步对
TokenCache
的所有访问

一个更简单的解决方案是使用

(我将其用于整个Web应用程序):


这是你的问题。
字典
类型不是线程安全的。请参阅。

单击“查看详细信息”,发布完整的堆栈跟踪。然后。。。你使用多线程吗?我们不能用这段代码复制它。我也在考虑“检查堆栈跟踪”,但这听起来像是intellitrace的工作。@DatVM:你将在10次中遇到9次并发问题。根据答案使用
ConcurrentDictionary
,并小心该类中的任何其他成员。它也可能有并发问题。非常感谢,很高兴知道。我还将编辑标题,以便将来遇到问题的人可以搜索此主题。
// 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)) ...
}
    public static LoginTokenManager LoginTokenManager = new LoginTokenManager();