简体   繁体   中英

Parallel running Progress Bar "Indeterminate" on Login in WPF

Can someone help me on following problem?

I want to show a "Progress Bar" that is "Indeterminate = TRUE" while the user is connecting to SSH server. If the the connection to the server is successfull, then the MainWindow with progressbar should be closed and a new Window will be opened. The progressbar is placed on a other Window named "LoginState".

Here a little codexample how I tried it:

Code from Login Methode:

private async void Login(object sender, RoutedEventArgs e)
{
  loginstate.Show();
  dispatcherlogin = Dispatcher.BeginInvoke(DispatcherPriority.Normal, new DelegateLogin(ProcessLogin));
  await dispatcherlogin.Task;
  
  if(ProofIfUserActive() == true)
  {
     loginstate.Close();
     mainoverview.Show();
     Close();
  }

private void ProcessLogin()
{
   // SSH and MySQL Connection
}

My problem:

If the Button is pressed the Methode "Login" will be triggered. In this moment the progress bar appeares and the connection to the ssh server start. The problem is, that I can't see any progress in the progress bar while it's opened, and after the succesfull connection, the main window with the progressbar will be closed and the other window will be opened.

I tried it also with the Dsipatcher.Invoke Method, but without success. Is that even possible what I want, because how I unterstood it, the wpf application is runnung in UI "STA Thread". Multithread is not possible, because I got immedtiatly a Exception that only STA threads are allowed.

Thanks developers for the help;)

Dispatcher.BeginInvoke will ask the IU thread to do the login. So while the connection is being established the UI thread is blocked and cannot update any window or do anything else UI related.

To solve this the typical solution is to move the time consuming operation to a background thread. This can be done by using Task.Run . This would free the UI thread to update the UI and respond to user input.

A typical problem with running things on a background thread is trying to update the UI. This is not allowed, you will need a clean separation between any code that will be running in the background and UI code.

It is possible that some components (usually COM components) have more complicated rules regarding threading, but I would not expect MySQL or SSH to have such requirements.

You should not put the blocking code on the Dispatcher . Dispatcher is keeping the UI thread alive by implementing a message queue. If you let the Dispatcher execute your long running operation, you are blocking the message queue that holds jobs that execute UI related operations like input events and rendering - the UI freezes.

Instead execute the long running CPU bound operations on a background thread which you can await.

Please note: the best solution is always to use an existing async API of your server (or the library used to interact with your server).
For example the HttpClient exposes a naturally async API.
IO operations like connecting to a database are not CPU bound and should generally not be executed on a background thread using Task.Run !

private async void Login(object sender, RoutedEventArgs e)
{
  loginstate.Show();

  await Task.Run(ProcessLogin);

  loginstate.Close();
  
  ...
}

The cleaner solution is, in case your login service is event driven, to use TaskCompletionSource to implement asynchronous behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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