【问题标题】:asp.net core: "Operations that change non-concurrent collections must have exclusive access."asp.net core:“更改非并发集合的操作必须具有独占访问权限。”
【发布时间】:2020-06-26 15:14:34
【问题描述】:

我的服务器使用 MySqlConnector 并与 AWS 上的 MySQL 数据库通信。我在 MySQL 中存储了 5 分钟的 API 计数器块。这些 API 计数器随着每次 API 调用而递增,并由 ConcurrentDictionary 代码处理(这似乎不是问题)。这行代码最近引发了一个异常,它是通过 MySqlConnector 访问 MySQL 数据库表的 linq 查询的一部分:

await _context.ApiCounts.Where(c => c.ApiName == apiName && c.StartTime >= startTime).ToListAsync();

我以前从未见过这条线失败,但突然我的一台服务器开始在上面的线中抛出以下异常:

InvalidOperationException: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
at System.ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported
at System.Collections.Generic.Dictionary`2.FindEntry
at System.Collections.Generic.Dictionary`2.TryGetValue
at Remotion.Linq.Parsing.Structure.NodeTypeProviders.MethodInfoBasedNodeTypeRegistry.GetNodeType
at Remotion.Linq.Parsing.Structure.NodeTypeProviders.MethodInfoBasedNodeTypeRegistry.IsRegistered
at System.Linq.Enumerable.Any
at Remotion.Linq.Parsing.Structure.ExpressionTreeParser.GetQueryOperatorExpression
at Remotion.Linq.Parsing.ExpressionVisitors.SubQueryFindingExpressionVisitor.Visit
at System.Linq.Expressions.ExpressionVisitor.VisitBinary
at System.Linq.Expressions.BinaryExpression.Accept
at System.Linq.Expressions.ExpressionVisitor.VisitBinary
at System.Linq.Expressions.BinaryExpression.Accept
at System.Linq.Expressions.ExpressionVisitor.VisitLambda
at System.Linq.Expressions.Expression`1.Accept
at System.Linq.Enumerable+SelectListPartitionIterator`2.ToArray
at System.Linq.Enumerable.ToArray
at Remotion.Linq.Parsing.Structure.MethodCallExpressionParser.Parse
at Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseMethodCallExpression
at Remotion.Linq.Parsing.Structure.QueryParser.GetParsedQuery
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileAsyncQueryCore
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<>c__DisplayClass24_0`1.<CompileAsyncQuery>b__0
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.System.Collections.Generic.IAsyncEnumerable<TResult>.GetEnumerator
at System.Linq.AsyncEnumerable+<Aggregate_>d__6`3.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
at BlayFap.Controllers.ServerController+<GetCachedApiCount>d__13.MoveNext (E:\Projects\BlayFap\BlayFap\Controllers\ServerController.cs:342)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
at BlayFap.Controllers.ServerController+<GetApiCount>d__14.MoveNext (E:\Projects\BlayFap\BlayFap\Controllers\ServerController.cs:378)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__12.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextActionFilterAsync>d__10.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeInnerFilterAsync>d__14.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw

所有其他表都可以正常访问,但是从这里开始尝试使用 ApiCounts 表会导致上述异常。我实际上必须重新启动受影响的服务器才能清除错误。看起来此异常与 Dictionary 上的并发编辑有关,并且 Dictionary 似乎在 linq 代码中。我猜服务器可能陷入这样一种情况,即 EF 在执行 linq 语句时同时更新和写入某种数据,然后让 Dictionary 陷入奇怪的状态,但我不知道如何防止这种情况以及真正的问题在哪里。这是 .NET 的错误,还是我自己的?

更多信息:我不会在此函数中修改 ApiCounts 的结果,也不会调用 SaveChanges。但是,与此异步运行的代码(在另一个 REST 查询中)可以更新 ApiCounts 并调用 SaveChanges。

【问题讨论】:

    标签: c# entity-framework asp.net-core mysql-connector


    【解决方案1】:

    解决方案是更新到 EF 2.1.5 或更高版本。

    发生此错误时,我使用的是 EF 2.0.3。看起来有一个线程不安全的单例,这可能会导致我看到的同样的错误。这是github中的问题:https://github.com/dotnet/efcore/issues/12682

    【讨论】:

    【解决方案2】:

    就我而言,我遇到了同样的问题。花了几个小时后,我重新启动了 IIS 中的应用程序池,它开始像魅力一样工作。

    首先,我尝试在不同的环境中复制该问题。它只发生在 PROD 环境中。所以我重新启动了 IIS 应用程序池,它给了我预期的输出

    【讨论】:

    • 重新启动应用程序池永远不会修复任何问题。异常很快就会出现。
    • 你好@GertArnold,好的。也许。让我等待问题回来。如果问题重新打开,我会更新
    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 2011-10-10
    • 2018-03-19
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 2022-06-22
    • 1970-01-01
    相关资源
    最近更新 更多