Почему Dispose вызывается до завершения асинхронной задачи? - PullRequest
1 голос
/ 12 апреля 2019

Я недавно наткнулся на эту странную ошибку.Похоже, что один из моих объектов удаляется до того, как мой метод завершит все асинхронные задачи.Но давайте посмотрим.

У меня есть тот асинхронный метод, который заполняет мою базу данных.Он вызывается в Startup классе в Configure методе.

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();
                }
            }
        }

И этот метод из DatabaseInitializer class:

    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();
    }

Дело в том, что если я использую ContinueWithчтобы связать задачи, он бросает System.ObjectDisposedException на userManager объект.Но мне нужно использовать ContinueWith, потому что мне нужно 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));
            }
        }

А также мой 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;
        }
    }

Мой вопрос:

Почему мой объект утилизируется до завершения всех задач?

Я полагаю, это из-заusing.Также я обнаружил, что Вопрос , но не прояснил ситуацию для меня.

@ Обновление

В соответствии с предложением @PanagiotisKanavos я удалил оператор using, и он решил моюустранение проблемы.Спасибо!

1 Ответ

0 голосов
/ 12 апреля 2019

Вы ожидаете только продолжения задания.Вместо:

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

... попробуйте:

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