First of all, I want to mention that I am kinda new to WPF, I just start learning it a few months ago and I am using code behind atm, going to MVVM later... So, Im trying to create a simple program for my discord bot but I want to keep it responsive whenever a database action is going on, meaning my program cannot block while i am -for example- logging into my program. I have a way to archive this but it feels like i am doing something wrong or using Tasking wrong.
I use await Task.Run(() => { code here }) but then inside this task I also need to use the Dispatcher every time I want to update a control and there is where I wonder if i do this all the correct way, is it normal to use the dispatcher inside a Task.Run every time you need to update controls or am I overusing this / doing it wrong?
Currently it works as intented, but I am worried I am overdoing something or going into the wrong direction because for me it seems silly to use the dispatcher every time for updating a control but maybe this is just the way it has to be, i am still new to WPF, this is also my first program i ever did in WPF
Sorry if my english is not so good, i try my best to explain this
I have a sort of solution but the use of Dispatcher inside Tasking seems to me not the correct way, this is the first time im doing this in WPF, I googled around a lot but see people using background workers or threading instead but this still seems to block my UI
// This button I use to -for this example- login in my program
// I load a ContentPresenter over my program showing its 'loading'
// Then I try login
private async void BtnLogin_Click(object sender, RoutedEventArgs e)
{
  cpLoader.Visibility = Visibility.Visible;
  await TryLoginAsync();
}
// Then here i do the login with tasking
// But here i also need to use dispatcher when updating controls
// So I wonder if this is done correctly
private async Task TryLoginAsync()
{
  var username = txtUsername.Text.Trim();
  var password = txtPassword.Password.Trim();
  if (!string.IsNullOrWhiteSpace(username) && !string.IsNullOrWhiteSpace(password))
  {
    await Task.Run(() =>
    {
      try
      {
        var programAdmin = _dbAdmins.FindBy(x => x.Username.ToLower() == username.ToLower());
        if (programAdmin != null)
        {
          if (string.Equals(EncryptionManager.Decrypt(BotDBConfiguration.EncryptionKey, programAdmin.Password), password))
          {
            programAdmin.DateLastLogin = DateTime.Now;
            programAdmin.TotalLogins += 1;
            _dbAdmins.Update(programAdmin);
            Dispatcher.BeginInvoke(new Action(() =>
            {
              var firstTimeLoginPanel = new UpdatePasswordWindow(programAdmin);
              firstTimeLoginPanel.Show();
              Close();
            }));
          }
          else
          {
            Dispatcher.BeginInvoke(new Action(() =>
            {
              cpLoader.Visibility = Visibility.Collapsed;
              AlertManager.ShowAlertMessage("Password error", "The given password is incorrect, please try again...");
            }));
          }
        }
        else
        {
          Dispatcher.BeginInvoke(new Action(() =>
          {
            cpLoader.Visibility = Visibility.Collapsed;
            AlertManager.ShowAlertMessage("Admin not found", "The given username cannot be found in the admin database, please try again...");
          }));
        }
      }
      catch (Exception)
      {
        Dispatcher.BeginInvoke(new Action(() =>
        {
          cpLoader.Visibility = Visibility.Collapsed;
          AlertManager.ShowAlertMessage("Connection error", "Cannot connect to the database, please try again later...");
        }));
      }
    });
  }
  else
  {
    cpLoader.Visibility = Visibility.Collapsed;
    AlertManager.ShowAlertMessage("Missing information", "Please fill in all the required information...");
  }
  }
 
     
    