【问题标题】:How do I make sure the UI is updated during long running processes in a WPF application?如何确保在 WPF 应用程序中长时间运行的进程期间更新 UI?
【发布时间】:2016-03-11 15:07:25
【问题描述】:

在遵循 MVVM 模式的 WPF 应用程序中,我遇到了一个常见问题,即用户单击一个按钮会触发 ViewModel 中的事件。此事件应启用“请稍候”微调器动画,执行一些可能需要几秒钟的处理,然后隐藏微调器。我不太确定可以使用哪种好的模式来确保始终显示微调器动画。

例如,我有一个登录过程,它执行以下操作:

  • 显示微调器(将 VM 上的属性设置为 true,微调器已绑定到它)
  • 尝试连接到服务器(可能需要几秒钟,具体取决于连接)
  • 失败时,显示失败消息
  • 成功后,保存有关用户的一些信息,以便应用的其余部分使用。

我发现微调器从未真正出现过。我曾尝试将运行时间较长的进程封装在 Task.Run 调用中,但这似乎没有帮助。

下面是代码的大致样子:

// 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;
    } 
}

【问题讨论】:

  • 所以 AuthenticationIsVisible = true;是什么应该激活微调器?
  • 对不起,是的。绑定确实有效(如果我在 ViewModel 的构造函数中将其设置为 true,它会显示为 0,因此这不仅仅是绑定失败的情况。我更新了上面的代码以显示更多内容。
  • 但是你正在阻止 .Wait();并且 NotifyOfPropertyChange 不会发送到 UI。有一种方法可以强制 UI 发布 - 在 WPF Refresh 上搜索。

标签: wpf asynchronous mvvm progress-bar statusbar


【解决方案1】:

正确的方法是不要阻塞 UI 线程(这是您现在使用 .Wait() 所做的),而是使用 AsyncAwait。

private Task<AuthCode> Authenticate()
{
    return Task.Run<AuthCode>(()=> 
    {
        return _client.Authenticate(); 
    });
}

public async void Login()
{
    AuthenticationIsVisible = true;
    AuthCode result = await Authenticate();
    AuthenticationIsVisible = false;
}

【讨论】:

    猜你喜欢
    • 2013-09-14
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    相关资源
    最近更新 更多