简体   繁体   English

为什么在完成异步任务之前调用Dispose?

[英]Why is Dispose called before its finishes async task?

I've recently stumbled on this strange error. 我最近偶然发现了这个奇怪的错误。 It looks like one of my object is disposing before my method finish all async Task. 看来我的对象之一正在处置,然后我的方法完成所有异步Task。 But let's take a look. 但是,让我们看看。

I have that async method which seeds my database. 我有一个异步方法为我的数据库播种。 It's called in Startup class in Configure method. Configure方法的Startup类中调用它。

private void InitDatabase(IApplicationBuilder app) {
            using (var scope = app.ApplicationServices.CreateScope()) {
                var services = scope.ServiceProvider;
                try {
                    var context = services.GetRequiredService<GrabGoContext>();
                    new DatabaseInitializer().InitializeAsync(context,
                        services.GetService(typeof(UserManager<User>)) as UserManager<User>,
                        services.GetService(typeof(SignInManager<User>)) as SignInManager<User>,
                        services.GetService(typeof(RoleManager<IdentityRole<int>>)) as RoleManager<IdentityRole<int>>,
                        _logger).Wait();
                    _logger.LogDebug("Database initialization finished.");
                }
                catch (Exception ex) {
                    _logger.LogError(ex, "An error occurred while seeding the database.");
                    if (Debugger.IsAttached) Debugger.Break();
                }
            }
        }

And that method from DatabaseInitializer class: 而来自DatabaseInitializer类的方法:

    public async Task InitializeAsync(GrabGoContext context,
        UserManager<User> userManager,
        SignInManager<User> signInManager,
        RoleManager<IdentityRole<int>> roleManager,
        ILogger<Startup> logger) {

        if(IsDatabaseInialized) return;
        IsDatabaseInialized = true;
        await context.Database.EnsureCreatedAsync();
        await AddStores(context);
        await AddProducts(context);
        await AddRoles(roleManager)
            .ContinueWith(t => AddRolesToUsers(userManager)); // <- Here throws exception "System.ObjectDisposedException" for object `userManager`
        await AddUsers(userManager);
        await context.SaveChangesAsync();
    }

The thing is that if I use ContinueWith to chain Tasks, it throws System.ObjectDisposedException on userManager object. 问题是,如果我使用ContinueWith链接Tasks,则会在userManager对象上引发System.ObjectDisposedException But I need to use ContinueWith , because I need Roles before I will assign users to that roles. 但我需要使用ContinueWith ,因为我需要Roles之前,我都会将用户分配到该角色。

My methods responsible for adding roles 我的方法负责添加角色

        private async Task AddRoles(RoleManager<IdentityRole<int>> roleManager) {
            if (await roleManager.Roles.AnyAsync()) return;

            var roles = (List<IdentityRole<int>>) new RolesListExample().GetExamples();
            foreach (var role in roles) {
                var result = await roleManager.CreateAsync(role);
                if(!result.Succeeded) throw new ApplicationException("Erros while adding roles: " +
                                                                     JsonConvert.SerializeObject(result.Errors));
            }
        }

        private async Task AddRolesToUsers(UserManager<User> userManager) {
            var registerModels = (List<RegisterModel>)new RegisterListRequestExample().GetExamples();
            foreach(var registerModel in registerModels) {
                var user = await userManager.FindByEmailAsync(registerModel.Email);
                var result = await userManager.AddToRoleAsync(user, registerModel.Role.ToString());
                if(!result.Succeeded)
                    throw new ApplicationException("Erros while adding roles to user: " +
                                                   JsonConvert.SerializeObject(result.Errors));
            }
        }

And also my RolesListExample class : 还有我的RolesListExample类:

    public class RolesListExample : IExamplesProvider {
        /// <inheritdoc />
        public object GetExamples() {
            var roles = new List<IdentityRole<int>>();
            foreach (var availableRole in (AvailableRoles[]) Enum.GetValues(typeof(AvailableRoles))) {
                roles.Add(new IdentityRole<int>(availableRole.ToString()));
            }
            return roles;
        }
    }

My question is: 我的问题是:

Why is my object disposing before all Tasks are finished? 为什么我的对象在所有任务完成之前就被处置了?

I assume that's because of the using . 我认为那是因为using Also I found that Question , but didn't clarify situation for me. 我也找到了Question ,但没有为我澄清情况。

@Update @更新

As suggested by @PanagiotisKanavos I removed using statement and it solved my disposing problem. 正如@PanagiotisKanavos所建议的那样,我删除了using语句,它解决了我的处置问题。 Thanks! 谢谢!

You are awaiting only the continuation of the task. 您仅在等待任务的继续。 Instead of: 代替:

await AddRoles(roleManager).ContinueWith(t => AddRolesToUsers(userManager));

...try: ...尝试:

var task1 = AddRoles(roleManager);
var task2 = task1.ContinueWith(t => AddRolesToUsers(userManager));
await task1;
await task2;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM