簡體   English   中英

如何使用Async在ASP.NET 5 Startup.cs中為用戶設定種子

[英]How to seed Users in ASP.NET 5 Startup.cs with Async

我正在嘗試在ASP.NET 5應用程序中創建一個初始的“超級用戶”。 使用MVC 6 / EF7的最新模板文件。

我可以按照這里列出的例子:

http://wildermuth.com/2015/3/17/A_Look_at_ASP_NET_5_Part_3_-_EF7

這很好 - 直到我嘗試執行異步方法。 例如:

await _userManager.CreateAsync(user, "P@55w0rd!");

甚至:

await _context.SaveChangesAsync();

同步方法可以正常工作,此代碼也可以在Startup.cs Configure{...}之外執行。

我在申請開始時得到了“白色死亡之屏”。 我會在沒有異步的情況下完成所有操作,但我認為UserManager在Identity 3.0中沒有Create()

這是我不理解異步編程還是應該可行?

編輯 :添加了整個電話:

定義Seeder類和創建用戶的方法:

  public class Seeder
    {
        private ApplicationDbContext _context;
        private UserManager<ApplicationUser> _userManager;

        public Seeder(
            ApplicationDbContext context,
            UserManager<ApplicationUser> userManager)
        {
            _context = context;
            _userManager = userManager;
        }

        public async Task Seed()
        {
            await CreateUsersAsync();
        }

        public async Task CreateUsersAsync()
        {
            var user = await _userManager.FindByEmailAsync("superuser@superuser.com");

            if (user == null)
            {
                var company = _context.Company.First(x => x.Name == "Acme Ltd");

                user = new ApplicationUser
                {
                    UserName = "superuser@superuser.com",
                    Email = "superuser@superuser.com",
                    CreatedDate = DateTime.Now,
                    IsActive = true,
                    CompanyID = company.CompanyId
                };

                await _userManager.CreateAsync(user, "P@55w0rd!!");

            }
        }
    }

配置服務:

public void ConfigureServices(IServiceCollection services)
{
...
services.AddTransient<Seeder>();
...
}

叫它:

public async void Configure(Seeder seeder)
{
...
await seeder.Seed();
...
}

有趣的是; 它確實創建了用戶 - 它只是不會繼續。 所以它第二次執行user != null並且執行正常。

我認為問題是因為簽名形成了死鎖

public async void Configure(Seeder seeder).

由於它返回void,因此等待的Task永遠不會返回給創建死鎖的調用者。 你能做到嗎:

public async Task Configure(Seeder seeder).

我還沒有開始使用MVC 6,:(所以我可能會遺漏一些東西。但這就是為什么會出現僵局。

編輯:

由於您無法更改Configure的簽名,因此請創建一個名為ConfigureAsync的方法,該方法返回Task類型。 現在用你的用戶管理器代碼按照慣例等待它並從Configure調用ConfigureAsync但等待它。

ConfigureAsync.ConfigureAwait(false).Wait()

ConfigureAwait(false)用於防止等待異步方法完成的潛在死鎖。

完整示例:

public void Configure(Seeder seeder)
{
    //Edited due to typo/bad syntax.
    ConfigureAsync(seeder).Wait();
}

public async Task ConfigureAsync(Seeder seeder)
{
   //Now treat this like true async/await.
   await seeder.Seed().ConfigureAwait(false);
}

如果你在這里遇到死鎖,也許你的播種機應該是同步的? 我會避免在ASP.NET上下文中使用Task.Run(),因為這將首先通過占用兩個請求線程來完全打敗async / await的目的,如果同步完成,那么這兩個請求線程就完成了。

有時,您需要實現同步接口,但您只能使用異步API。 沒有完美的解決方案。

幸運的是,此代碼僅被調用一次,因此性能問題無關緊要。 您可以通過異步橋進行臟同步:

public void ConfigureServices(IServiceCollection services)
{
    ConfigureServicesImpl(services).Wait(); //bridge
}

public async Task ConfigureServicesImpl(IServiceCollection services)
{
   await ...;
}

您可能需要插入死鎖保護,例如ConfigureAwait(false)Task.Run(() => ...).Wait()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM