BackgroundWorker.RunWorkerCompleted

Есть 2 глобальные переменные. Переменная controlDisable привязана к свойству IsEnabled элементов окна. :

private bool completedLogin = true;
    public bool CompletedLogin
    {
        get
        {
            return completedLogin;
        }
        set
        {
            completedLogin = value;
            NotifyPropertyChanged();
        }
    }

private bool controlDisable = true;
    public bool ControlDisable
    {
        get
        {
            return controlDisable;
        }
        set
        {
            controlDisable = value;
            NotifyPropertyChanged();
        }
    }

Есть метод, который выполняется при нажатии на кнопку в другом потоке(используется класс BackgroundWorker):

 private RelayCommand loginCommand;

    public RelayCommand LoginCommand
    {
        get
        {
            return loginCommand ??
              (loginCommand = new RelayCommand(obj =>
              {
                  ControlDisable = false;
                  CompletedLogin = false;
                  Password = GetPassword(obj);
                  worker = new BackgroundWorker();
                  worker.DoWork += (obj, ea) => LoginUser();
                  worker.RunWorkerAsync();
                  worker.RunWorkerCompleted += (obj, ea) => OpenGeneral();
              }));
        }
    }

private async void LoginUser()
    {
        if (Login != "" && Password != "")
        {
            using (MSGCoreContext db = new MSGCoreContext())
            {
                user = await db.Users.FirstOrDefaultAsync(u => u.Login == Login);

                if (user != null)
                {
                    userId = user.UserId;
                    userRole = user.Role;

                    if (PBKDF2HashHelper.VerifyPassword(Password, user.Password))
                    {
                        CompletedLogin = true;
                    }
                    else { Warning = "Неверный логин или пароль!"; CompletedLogin = false; ControlDisable = true; }
                }
                else { Warning = "Пользователь не существует!"; CompletedLogin = false; ControlDisable = true; }
            }
        }
        else
        {
            Warning = "Заполните все поля!";
            CompletedLogin = false;
            ControlDisable = true;
        }
    }

После того как закончится выполнение метода LoginUser, срабатывает событие RunWorkerCompleted, которое вызывает метод OpenGeneral:

private void OpenGeneral()
    {
        if (CompletedLogin)
        {
            var displayRootRegistry = (Application.Current as App).displayRootRegistry;
            var dialogWindowViewModel = new GeneralViewModel(Login, userRole);
            displayRootRegistry.ShowPresentation(dialogWindowViewModel);
            Application.Current.MainWindow.Close();
        }
    }

Значение ControlDisable изменяется и элементы в окне переходят в состояние IsEnabled = false. А значение переменной CompletedLogin в методе OpenGeneral всегда имеет значение false, как сделать чтобы значение CompletedLogin тоже изменялось?


Ответы (1 шт):

Автор решения: Zan Person

Все стало корректно работать после того как я убрал из метода LoginUser модификатор async и выражение await:

private void LoginUser()
{
    if (Login != "" && Password != "")
    {
        using (MSGCoreContext db = new MSGCoreContext())
        {
            user = db.Users.FirstOrDefault(u => u.Login == Login);

            if (user != null)
            {
                userId = user.UserId;
                userRole = user.Role;

                if (PBKDF2HashHelper.VerifyPassword(Password, user.Password))
                {
                    CompletedLogin = true;
                }
                else { Warning = "Неверный логин или пароль!"; CompletedLogin = false; ControlDisable = true; }
            }
            else { Warning = "Пользователь не существует!"; CompletedLogin = false; ControlDisable = true; }
        }
    }
    else
    {
        Warning = "Заполните все поля!";
        CompletedLogin = false;
        ControlDisable = true;
    }
}

UPDATE: Для того, чтобы оставить метод LoginUser асинхронным, пришлось отказаться от использования класса BackgroundWorker, т.к он не очень хорошо работает с async/await. Я заменил его на класс Task:

Измененная команда:

public RelayCommand LoginCommand
    {
        get
        {
            return loginCommand ??
              (loginCommand = new RelayCommand(async obj =>
              {
                  ControlDisable = false;
                  CompletedLogin = false;
                  LoadingVisability = true;
                  Password = GetPassword(obj);
                  await Task.Run(() => LoginUser());
                  OpenGeneral();
              }));
        }
    }

Измененный метод LoginUser:

private async Task LoginUser()
    {
        if (Login != "" && Password != "")
        {
            using (MSGCoreContext db = new MSGCoreContext())
            {
                user =  await db.Users.FirstOrDefaultAsync(u => u.Login == Login);

                if (user != null)
                {
                    userId = user.UserId;
                    userRole = user.Role;

                    if (PBKDF2HashHelper.VerifyPassword(Password, user.Password))
                    {
                        CompletedLogin = true;
                        LoadingVisability = false;
                    }
                    else { Warning = "Неверный логин или пароль!"; CompletedLogin = false; ControlDisable = true; LoadingVisability = false; }
                }
                else { Warning = "Пользователь не существует!"; CompletedLogin = false; ControlDisable = true; LoadingVisability = false; }
            }
        }
        else
        {
            Warning = "Заполните все поля!";
            CompletedLogin = false;
            ControlDisable = true;
            LoadingVisability = false;
        }
    }
→ Ссылка