在 WPF 中登录时并行 运行 进度条 "Indeterminate"

Parallel running Progress Bar "Indeterminate" on Login in WPF

有人可以帮我解决以下问题吗?

我想在用户连接到 SSH 服务器时显示一个“不确定 = 真”的“进度条”。如果与服务器的连接成功,则应关闭带有进度条的 MainWindow 并打开一个新的 Window。进度条放在另一个名为“LoginState”的 Window 上。

这是我如何尝试的一个小代码示例:

来自登录方法的代码:

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
}

我的问题:

如果按下按钮,将触发方法“登录”。此时会出现进度条并开始连接到 ssh 服务器。问题是,我在进度条打开时看不到任何进度,连接成功后,主 window 与进度条将关闭,另一个 window 将打开.

我也尝试了 Dsipatcher.Invoke 方法,但没有成功。这甚至可能是我想要的,因为我如何理解它,wpf 应用程序在 UI“STA 线程”中运行。多线程是不可能的,因为我立即得到一个异常,只允许 STA 线程。

感谢开发者的帮助 ;)

Dispatcher.BeginInvoke 将要求 IU 线程进行登录。因此,在建立连接时,UI 线程被阻塞,无法更新任何 window 或做任何其他 UI 相关的事情。

要解决此问题,典型的解决方案是将耗时的操作移至后台线程。这可以通过使用 Task.Run 来完成。这将释放 UI 线程来更新 UI 并响应用户输入。

后台线程上 运行 的一个典型问题是尝试更新 UI。这是不允许的,您需要将后台的 运行 代码与 UI 代码完全分开。

可能某些组件(通常是 COM 组件)有更复杂的线程规则,但我不希望 MySQL 或 SSH 有这样的要求。

您不应将阻止代码放在 Dispatcher 上。 Dispatcher 通过实现消息队列使 UI 线程保持活动状态。如果您让 Dispatcher 执行您的长 运行 操作,您将阻塞包含执行 UI 相关操作(如输入事件和渲染)的作业的消息队列 - UI 冻结.

而是在您可以等待的后台线程上执行长 运行 CPU 绑定操作。

请注意:最好的解决方案始终是使用服务器的现有异步 API(或用于与服务器交互的库)。
例如 HttpClient 公开一个自然异步 API.
像连接数据库这样的 IO 操作不受 CPU 约束,通常不应使用 Task.Run!

在后台线程上执行
private async void Login(object sender, RoutedEventArgs e)
{
  loginstate.Show();

  await Task.Run(ProcessLogin);

  loginstate.Close();
  
  ...
}

更简洁的解决方案是,如果您的登录服务是事件驱动的,则使用 TaskCompletionSource 实现异步行为。