如何确保 UI 在 WPF 应用程序的长 运行 进程中得到更新?
How do I make sure the UI is updated during long running processes in a WPF application?
在遵循 MVVM 模式的 WPF 应用程序中,我 运行 遇到了一个常见问题,即用户单击按钮会触发 ViewModel 中的事件。此事件应启用 "Please Wait" 微调器动画,执行一些可能需要几秒钟的处理,然后隐藏微调器。我不确定是否可以使用一个好的模式来确保微调器动画始终出现。
例如,我有一个执行以下操作的登录过程:
- 显示微调器(将 VM 上的 属性 设置为 true,微调器绑定到它)
- 尝试连接到服务器(可能需要几秒钟,具体取决于连接情况)
- 失败时,显示失败消息
- 成功后,保存一些关于用户的信息,以便应用程序的其余部分可以使用。
我发现微调器实际上从未出现过。我曾尝试在 Task.Run 调用中包装较长的 运行ning 过程,但这似乎没有帮助。
代码大致如下:
// When true, spinner should be visible
protected bool _authenticatingIsVisible = false;
public bool AuthenticatingIsVisible
{
get { return _authenticatingIsVisible; }
set
{
_authenticatingIsVisible = value;
NotifyOfPropertyChange(() => AuthenticatingIsVisible);
}
}
public void Login()
{
try
{
AuthenticationIsVisible = true;
AuthCode result = AuthCode.NoAuthenticated;
Task.Run(() => { result = _client.Authenticate() }).Wait();
AuthenticationIsVisible = false;
if (result == AuthCode.Authenticated)
{
// Bit of misc. code to set up the environment
// Another check to see if something has failed
// If it has, displays a dialog.
// ex.
var error = new Error("Something Failed", "Details Here", Answer.Ok);
var vm = new DialogViewModel() { Dialog = error };
_win.ShowDialog(vm);
return;
}
else
{
DisplayAuthMessage(result);
}
}
finally
{
AuthenticationIsVisible = false;
}
}
正确的方法是不阻塞 UI 线程(这是您现在使用 .Wait()
所做的),而是使用 Async Await。
private Task<AuthCode> Authenticate()
{
return Task.Run<AuthCode>(()=>
{
return _client.Authenticate();
});
}
public async void Login()
{
AuthenticationIsVisible = true;
AuthCode result = await Authenticate();
AuthenticationIsVisible = false;
}
在遵循 MVVM 模式的 WPF 应用程序中,我 运行 遇到了一个常见问题,即用户单击按钮会触发 ViewModel 中的事件。此事件应启用 "Please Wait" 微调器动画,执行一些可能需要几秒钟的处理,然后隐藏微调器。我不确定是否可以使用一个好的模式来确保微调器动画始终出现。
例如,我有一个执行以下操作的登录过程:
- 显示微调器(将 VM 上的 属性 设置为 true,微调器绑定到它)
- 尝试连接到服务器(可能需要几秒钟,具体取决于连接情况)
- 失败时,显示失败消息
- 成功后,保存一些关于用户的信息,以便应用程序的其余部分可以使用。
我发现微调器实际上从未出现过。我曾尝试在 Task.Run 调用中包装较长的 运行ning 过程,但这似乎没有帮助。
代码大致如下:
// When true, spinner should be visible
protected bool _authenticatingIsVisible = false;
public bool AuthenticatingIsVisible
{
get { return _authenticatingIsVisible; }
set
{
_authenticatingIsVisible = value;
NotifyOfPropertyChange(() => AuthenticatingIsVisible);
}
}
public void Login()
{
try
{
AuthenticationIsVisible = true;
AuthCode result = AuthCode.NoAuthenticated;
Task.Run(() => { result = _client.Authenticate() }).Wait();
AuthenticationIsVisible = false;
if (result == AuthCode.Authenticated)
{
// Bit of misc. code to set up the environment
// Another check to see if something has failed
// If it has, displays a dialog.
// ex.
var error = new Error("Something Failed", "Details Here", Answer.Ok);
var vm = new DialogViewModel() { Dialog = error };
_win.ShowDialog(vm);
return;
}
else
{
DisplayAuthMessage(result);
}
}
finally
{
AuthenticationIsVisible = false;
}
}
正确的方法是不阻塞 UI 线程(这是您现在使用 .Wait()
所做的),而是使用 Async Await。
private Task<AuthCode> Authenticate()
{
return Task.Run<AuthCode>(()=>
{
return _client.Authenticate();
});
}
public async void Login()
{
AuthenticationIsVisible = true;
AuthCode result = await Authenticate();
AuthenticationIsVisible = false;
}