在 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
实现异步行为。
有人可以帮我解决以下问题吗?
我想在用户连接到 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
实现异步行为。