【问题标题】:how to update viewmodel property that is fetched asynchronously?如何更新异步获取的视图模型属性?
【发布时间】:2019-03-30 00:05:25
【问题描述】:

在我的 FolderViewModel 中,我有

public string FolderPath
        {
            get
            {
                if (folderPath == null)
                {
                    GetFolderPathAsync();
                    return "Loading...";
                }
                return folderPath;
            }
            set
            {
                folderPath = value;
                Changed(nameof(FolderPath));
            }
        }

GetFolderPathAsync 是一种异步方法,它使服务器调用以获取路径并设置 FolderPath。

现在在另一个类中,我创建文件夹视图模型并以这种方式设置它们的路径

folderViewModel.FolderPath = parent.FolderPath+"/"+folder.Name;

问题在于,路径最终设置为“正在加载.../文件夹名称”,并且当父文件夹的文件夹路径在从服务器获取后从“正在加载...”更新时永远不会更新。我该如何解决?我不擅长线程,所以我真的不知道如何解决这个问题。我想知道是否有办法让 folderPath 的设置等待 GetFolderPathAsync 以某种方式完成?

感谢您的帮助!

【问题讨论】:

  • 属性不应启动异步操作。如果您从异步方法调用 GetFolderPathAsync 方法,您可以等待它,然后在完成后将数据绑定属性设置为“正在加载”。这假设 GetFolderPathAsync 返回一个 Task
  • 您可以简单地在GetFolderPathAsync() 之后添加一个继续运行的任务来调用和发出通知。

标签: c# wpf multithreading mvvm


【解决方案1】:

属性不应启动异步操作。这就是 C# 不支持 async 属性的主要原因。更多信息请参考@Stephen Cleary's blog

如果您改为从async 方法调用GetFolderPathAsync 方法,您可以await 它,然后在完成后将数据绑定属性设置为“正在加载...”。这假设GetFolderPathAsync 返回TaskTask<T>

public string FolderPath
{
    get
    {
        return folderPath;
    }
    set
    {
        folderPath = value;
        Changed(nameof(FolderPath));
    }
}
...
folderViewModel.FolderPath = parent.FolderPath+"/"+folder.Name;
await folderViewModel.GetFolderPathAsync();
folderViewModel.FolderPath = "Loading...";

另一种选择是使用ContinueWith 方法创建一个在任务完成时异步执行的延续:

if (folderPath == null)
{
    GetFolderPathAsync().ContinueWith(_ => 
    {
        folderPath = "Loading...";
        Changed(nameof(FolderPath));
    });
    return folderPath;
}

【讨论】:

  • @an007: 哪一部分没用?同样,从属性的 getter 调用异步方法是错误的,因此您应该重新考虑您的设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-08
  • 2014-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 2019-04-21
相关资源
最近更新 更多