如果我同时进行了more than one
API 调用,则出现错误
在上一个异步操作完成之前,在此上下文上启动了第二个操作。使用"await"确保在此上下文中调用另一个方法之前已完成任何异步操作。不保证任何实例成员都是线程安全的。
var identity = await base.currentUserService.CreateIdentity(user);
引发异常,因为两个请求同时发出,并且上一个请求的 CreateIdentity 方法仍未完成!
如何解决上述情况?
我想在上一个请求完成之前等待IsValidRequest
CustomKeyAuthenticationAttribute
呼入。
这是示例代码
public class CustomKeyAuthenticationAttribute : AuthorizeAttribute
{
[Dependency]
public IAuthService AuthService { get; set; }
public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
var isValid = await AuthService.IsValidRequest(key-from-request-header);
if(!isValid){
return;
}
await base.OnAuthorizationAsync(actionContext, cancellationToken);
}
}
// In side AuthService
public async Task<bool> IsValidRequest(string key)
{
if (key-in-db)
{
var user = await base.currentUserService.GetUserById(userId-from-request-headers);
var identity = await base.currentUserService.CreateIdentity(user);
var principal = new GenericPrincipal(identity.Result, new string[0]);
HttpContext.Current.User = principal;
return true;
}
return false
}
// Inside currentUserService.CreateIdentity method
public async Task<ClaimsIdentity> CreateIdentity(CustomUser user) {
return await userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
}
编辑
stackTrace: " at System.Data.Entity.Internal.ThrowingMonitor.EnsureNotEntered(( at System.Data.Entity.Internal.Linq.InternalSet
1.FindAsync(CancellationToken cancellationToken, Object[] keyValues) at System.Data.Entity.DbSet
1.FindAsync(CancelToken cancelToken, Object[] keyValues( at System.Data.Entity.DbSet1.FindAsync(Object[] keyValues) at Microsoft.AspNet.Identity.EntityFramework.EntityStore
1.GetByIdAsync(Object 同上( 在 Microsoft.AspNet.Identity.EntityFramework.UserStore6.<GetUserAggregateAsync>d__6c.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.TaskExtensions.CultureAwaiter
1.GetResult(( 在 Microsoft.AspNet.Identity.UserManager2.<GetRolesAsync>d__ac.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.TaskExtensions.CultureAwaiter
1.GetResult(( 在 Microsoft.AspNet.Identity.ClaimsIdentityFactory2.<CreateAsync>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.Runtime.CompilerServices.TaskAwaiter
1.GetResult((
我需要查看背后的代码
var identity = await base.currentUserService.CreateIdentity(user);
但我的猜测是,您将 DbContext 设置为各种请求之间的共享实例。您需要为每个线程使用不同的上下文。
在此处查看此问题以获取更多信息,因为我认为这是相同的问题。
实体框架文档的另一个类似问题