【发布时间】:2014-12-08 17:19:45
【问题描述】:
我在使用 Identity v2.0.0.0、EF 6、Castle Windsor IOC Container、Microsoft SQL Server 2005 的 asp.net MVC5 Web 应用程序中遇到了这个问题
我正在尝试使用 UserManagerExtensions,FindById() 方法获取当前登录的用户,但它抛出错误“System.NotSupportedException:在前一个异步操作完成之前在此上下文上启动了第二个操作。使用“等待”以确保在调用此上下文中的另一个方法之前已完成任何异步操作。不保证任何实例成员都是线程安全的"
我从堆栈跟踪中了解到是“AsyncHelper.RunSync()”导致问题,我没有在我的代码中使用任何异步函数,而是使用 AsyncHelper 的“FindById()” 参考 -: http://www.symbolsource.org/MyGet/Metadata/aspnetwebstacknightly/Project/Microsoft.AspNet.Identity.Core/2.0.0-beta1-140129/Release/Default/Microsoft.AspNet.Identity.Core/Microsoft.AspNet.Identity.Core/Extensions/UserManagerExtensions.cs?ImageName=Microsoft.AspNet.Identity.Core
关于这个身份错误的信息似乎很少,我在我的应用程序的不同部分使用当前登录用户的详细信息,当调用我的服务层中的 GetCurrentLoggedInUser() 函数时,这个错误似乎随机发生。请帮忙....
我的代码和堆栈跟踪如下---- 注意:我在这里发现了另一个类似类型的事件:https://aspnetidentity.codeplex.com/workitem/2408
全球.asax:
.Register(Component
.For<UserManager<ApplicationUser>>()
.UsingFactoryMethod((kernel, creationContext) =>
new TempoUserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext(ASPUserDatabaseConnectionString))))
.LifestylePerWebRequest()
)
.Register(Component
.For<RoleManager<IdentityRole>>()
.UsingFactoryMethod((kernel, creationContext) =>
new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext(ASPUserDatabaseConnectionString))))
.LifestylePerWebRequest()
)
服务层代码:
public class GenericService
{
protected IRepository _repository;
protected UserManager<ApplicationUser> _userManager;
public GenericService(IRepository repository, UserManager<ApplicationUser> userManager)
{
_repository = repository;
_userManager = userManager;
}
public ApplicationUser GetCurrentLoggedInUser()
{
//Error is thrown when calling this
return _userManager.FindById(HttpContext.Current.User.Identity.GetUserId());
}
}
下面是堆栈跟踪,
System.NotSupportedException: 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.
at System.Data.Entity.Internal.ThrowingMonitor.Enter()
at System.Data.Entity.Core.Objects.ObjectQuery`1.<GetResultsAsync>d__e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Data.Entity.Internal.LazyAsyncEnumerator`1.<FirstMoveNextAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Data.Entity.Infrastructure.IDbAsyncEnumerableExtensions.<FirstOrDefaultAsync>d__25`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
**at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Identity.AsyncHelper.RunSync[TResult](Func`1 func)
at Microsoft.AspNet.Identity.UserManagerExtensions.FindById[TUser,TKey](UserManager`2 manager, TKey userId)
at Tempo.BusinessLogics.Services.GenericService.GetCurrentLoggedInUser()
at Tempo.BusinessLogics.Services.GenericService.GetCurrentLoggedInUserID()
at Tempo.BusinessLogics.Services.TimeService.UpdateSignOfChildDetails(EntryLog toUpdate, Boolean targetSignState)
at Tempo.BusinessLogics.Services.TimeService.SignEntries(SignOffs sgnOffs, Byte flag)
at Tempo.Controllers.TimeEntryController.SignOffAll(String cbxStatus)**
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.<>c__DisplayClass1.<WrapVoidAction>b__0(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass48.<InvokeActionMethodFilterAsynchronouslyRecursive>b__41()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<>c__DisplayClass2b.<BeginInvokeAction>b__1c()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
【问题讨论】:
-
您如何创建
_userManager并使用它? -
谢谢,我已经更新了服务层代码,它显示了它是如何注入其中的,Castle Windsor 创建并将 UserManager 注入到我正在使用它的服务层中,就像它在函数中一样。
-
我的猜测是,如果您每次致电
GetCurrentLoggedInUser()时都会收到一个新的UserManager<ApplicationUser>,那么您将不会遇到此问题。每个上下文只允许一个异步调用。我以前没有使用过 Windsor,但LifestylePerWebRequest()听起来是正确的选择,但也许它会为不同的请求返回相同的实例?尝试在 GetCurrentUser 中创建一个新的 UserManager,看看问题是否消失,不是说这是解决方案,而是缩小问题范围。
标签: c# asp.net-mvc entity-framework asp.net-mvc-5 asp.net-identity