【问题标题】:Second async operation started...don't see how第二个异步操作开始了......不知道如何
【发布时间】:2019-07-16 06:21:17
【问题描述】:

在前一个异步操作结束之前,我收到了关于在上下文中开始的第二个异步操作的错误,但我没有看到它发生在哪里。这是我正在使用的代码。每个异步调用都在使用等待,那么我做错了什么?

这是一个 Web API 2 调用的方法。

public async Task<IHttpActionResult> SendAssessmentArsAsync(int assessmentId) {
    using (var context = new LAMPEntities()) {
        var assessment = await context.EHS_Assessment_Audit.AsNoTracking().Where(x => x.id == assessmentId).FirstOrDefaultAsync();

        var arsQuery = from r in context.EHS_Assessment_Audit_AR.AsNoTracking()
                       where r.EHS_Assessment_Audit_Id == assessmentId
                       join w in context.Worker on r.Assignee_WWID equals w.WWID
                       select new {
                           w.Email,
                           w.Full_Name,
                           r.AR,
                           r.Due_Date
                       };

        var ars = await arsQuery.ToArrayAsync();

        var lab = from s in context.Lab_Space.AsNoTracking()
                  where s.id == assessment.Lab_Space.id
                  join w in context.Worker.AsNoTracking() on s.Contact_WWID equals w.WWID
                  where w.Email != null
                  join d_join in context.Worker.AsNoTracking() on s.Delegate equals d_join.WWID into d_grp
                  from d in d_grp.DefaultIfEmpty()
                  select new {
                      Owner = w.Email,
                      Delegate = d.Email,
                      Barcode = s.Entry_Bar_Code,
                      Label = s.Floor_Space_Label,
                      Id = s.id
                  };

        var mails = await lab.FirstAsync();

当它到达最后一行时就是抛出异常的地方。

异常信息:

在前一个异步操作完成之前,在此上下文上启动了第二个操作。使用 'await' 确保在此上下文中调用另一个方法之前所有异步操作都已完成。不保证任何实例成员都是线程安全的。

以下是通过 web 服务调用显示的异常:

b__a()
 at System.Data.Entity.Core.Objects.ObjectContext.d__3d`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.d__9`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Data.Entity.Utilities.TaskExtensions.CultureAwaiter`1.GetResult()
 at System.Data.Entity.Core.Objects.ObjectQuery`1.d__e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Data.Entity.Utilities.TaskExtensions.CultureAwaiter`1.GetResult()
 at System.Data.Entity.Internal.LazyAsyncEnumerator`1.d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Data.Entity.Infrastructure.IDbAsyncEnumerableExtensions.d__1d`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
 at LabSORService.Controllers.EHSController.d__21.MoveNext() in ...\\Controllers\\EHSController.cs:line 854
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Threading.Tasks.TaskHelpersExtensions.d__1`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Web.Http.Controllers.ApiControllerActionInvoker.d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Web.Http.Controllers.ActionFilterResult.d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__15.MoveNext()" }
{
  "message": "An error has occurred.",
  "exceptionMessage": "A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.",
  "exceptionType": "System.NotSupportedException",
  "stackTrace": "   at System.Data.Entity.Core.Objects.ELinq.QueryParameterExpression.TryGetFieldOrPropertyValue(MemberExpression me, Object instance, Object& memberValue)
   at System.Data.Entity.Core.Objects.ELinq.QueryParameterExpression.TryEvaluatePath(Expression expression, ConstantExpression& constantExpression)
   at System.Data.Entity.Core.Objects.ELinq.QueryParameterExpression.EvaluateParameter(Object[] arguments)
   at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClassc.

【问题讨论】:

  • 您是否尝试使用来自不同线程的相同上下文?
  • 没有。它只是一个从 HTTP 请求调用的 Web api 方法(我将其添加到问题中)
  • 该操作从哪里获取上下文?上下文是在哪里创建的?您应该添加相关代码相关标签。 ASP.NET Web API 完整版还是核心版?上下文是否被注入,也许是一个单例?您也应该发布完整的异常,包括它的调用堆栈。您可以使用 Exception.ToString() 轻松实现。
  • 添加了 web api 2...标签。我现在也展示方法和上下文,对不起。
  • 异常的调用堆栈显示异常发生的位置以及导致该点的调用。这里发布的代码不应该通过,尽管它可以被极大地简化。调用堆栈可以提供有关发生了什么的提示。 Exception.ToString() 返回的完整异常文本包含消息、任何内部异常和完整的调用堆栈。

标签: entity-framework async-await asp.net-web-api2


【解决方案1】:

很有可能

where s.id == assessment.Lab_Space.id

正在不适当的时间触发 Lab_Space 导航属性的延迟加载。

假设您没有像 Lab_Space_Id 这样的显式 FK 属性(如果有,只需使用它而不是 Lab_Space.id),或者急切加载它(首选):

var assessment = await context.EHS_Assessment_Audit.AsNoTracking()
    .Include(x => x.Lab_Space) // <--
    .Where(x => x.id == assessmentId).FirstOrDefaultAsync();

或在查询之外对其进行评估:

var labSpaceId = assessment.Lab_Space.id; // <--
var lab = from s in context.Lab_Space.AsNoTracking()
          where s.id == labSpaceId // <--
          ...

请注意,在原始查询中,assessment.Lab_Space 访问只是记录在查询表达式树中。实际评估(因此触发延迟加载)作为查询执行的一部分发生。

【讨论】:

  • 非常感谢。更改为我不知道为什么我还没有使用的外键,解决了这个问题。
猜你喜欢
  • 2018-05-22
  • 2020-10-23
  • 1970-01-01
  • 1970-01-01
  • 2017-03-14
  • 2020-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多