编程语言
首页 > 编程语言> > c#-如何使用异步为ASP.NET 5 Startup.cs中的用户播种

c#-如何使用异步为ASP.NET 5 Startup.cs中的用户播种

作者:互联网

我正在尝试在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();
...
}

有趣的是;它确实会创建用户-只是不会继续.因此,第二次执行用户!= 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的目的,因为它占用了两个请求线程,如果它们是同步完成的话,它们只是在一个线程上完成的.

标签:async-await,c,asp-net-mvc,entity-framework
来源: https://codeday.me/bug/20191118/2031510.html