在ASP Identity Framework 2中,UserManager爲其許多異步方法提供了同步包裝。遺憾的是此同步包裝使用AsyncHelper,說FindById(...):ASP Identity Framework 2:UserManager同步方法將運行在_other_線程中,使得HttpContext.Current爲空
return AsyncHelper.RunSync(() => manager.FindByIdAsync(userId));
審視RunSync方法原來它運行在其他線程的方法:
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
var cultureUi = CultureInfo.CurrentUICulture;
var culture = CultureInfo.CurrentCulture;
return _myTaskFactory.StartNew(() =>
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = cultureUi;
return func();
}).Unwrap().GetAwaiter().GetResult();
}
然而,在這種其他線程HttpContext.Current將爲空,因爲它是線程本地的。不幸的是,ASP身份框架2依賴於HttpContext.Current,例如種子的方法調用InitializeIdentityForEF,它試圖訪問這樣的背景下,並拋出一個空引用異常:
protected override void Seed(ApplicationDbContext context)
{
InitializeIdentityForEF(context);
base.Seed(context);
}
//Create [email protected] with [email protected] in the Admin role
// ReSharper disable once InconsistentNaming
public static void InitializeIdentityForEF(ApplicationDbContext db)
{
var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();
我的主要問題:我怎樣才能調用UserManager的(或其他)異步方法,而不冒險編組到其他線程,其中HttpContext.Current將爲空,這可能會導致意外的行爲(在身份框架本身內)?顯然,提供的同步包裝是不可用的。
在有人問我爲什麼想要同步調用之前:假設我想在屬性get中使用UserManager,其中await不是一個選項。除此之外,同步包裝確實存在(出於我認爲的一個原因)僅僅不可用,或者至少引入了最糟糕的一種錯誤:在隨機地方隨機使用null。
你不能使用'.Result'屬性嗎?像'manager.FindByIdAsync(userId).Result;'我認爲沒有必要爲這兩個塊創建一個任務,直到結果填充(如'AsyncHelper') –
您是否真的試圖運行'Seed'方法'Global.asax.cs'? – trailmax
trailmax:否請從下面的「Seed方法隱式運行...」開始閱讀我的意見。 –