当我的属性引发PropertyChanged事件时,如何运行一些长操作? 例如:
class SomeClass : INotifyPropertyChanged
{
public ObservableConllection<Item> Items { get; set; }
public string Path
{
get => _path;
if (_path != value) {
_path = value;
OnPropertyChanged(nameof(Path));
// await Task.Run(()=> long operation, for example load some Items use "_path");
}
}
属性不能异步,我认为它是“正常的”。但是我该怎么办? 我认为这种情况经常发生。
答案 0 :(得分:1)
你应该阅读Stephen Cleary关于异步数据绑定属性的MSDN文章,他定义了一个名为NotifyTaskCompletion<T>
的“任务观察者”类,它实现了INotifyPropertyChanged
接口,并具有Result
属性你可以绑定到:
异步编程:异步MVVM应用程序的模式:数据绑定: https://msdn.microsoft.com/en-us/magazine/dn605875.aspx
public class MainViewModel : INotifyPropertyChanged
{
public string Path
{
get { return _path; }
set
{
if (_path != value)
{
_path = value;
OnPropertyChanged(nameof(Path));
AsyncProperty = new NotifyTaskCompletion<int>(YourAsyncMethod());
}
}
}
public NotifyTaskCompletion<string> AsyncProperty { get; private set; }
}
<Label Content="{Binding AsyncProperty.Result}"/>
答案 1 :(得分:0)
您可以使用var key = "SOFTWARE\\Microsoft\\Expression\\Encoder\\4.0";
using (var registryKey = Registry.LocalMachine.OpenSubKey(key))
{
if (registryKey == null)
{
using (var newKey = Registry.LocalMachine.CreateSubKey(key))
{
CheckInstallKey(newKey);
}
}
else
{
CheckInstallKey(registryKey);
}
}
而不使用Task.Run
。根据具体情况,它可能运行也可能不运作,对此没有普遍的答案。
您可以创建这样的方法来设置值,这是一种更加可靠的方法。但是,如果您需要数据绑定,则无法使用:
await
如果您需要数据绑定并且想要使用public async Task SetPath(string value)
{
if (_path != value) {
_path = value;
OnPropertyChanged(nameof(Path));
await Task.Run(()=> ...);
}
,那么通常最好的做法是使用定时器进行去抖动 - 您不希望在不受用户限制的情况下使用某些昂贵的操作,以便他可以冻结或崩溃应用程序。