C# 属性更改时运行长操作
当我的属性引发PropertyChanged事件时,如何运行一些长操作? 例如:C# 属性更改时运行长操作,c#,.net,wpf,async-await,task-parallel-library,C#,.net,Wpf,Async Await,Task Parallel Library,当我的属性引发PropertyChanged事件时,如何运行一些长操作? 例如: class SomeClass:INotifyPropertyChanged { 公共ObservableCollection项{get;set;} 公共字符串路径 { get=>\u路径; 如果(_路径!=值){ _路径=值; OnPropertyChanged(名称(路径)); //等待任务。运行(()=>长操作,例如加载某些项目使用“\u路径”); } } 属性不能是异步的,我认为它是“正常的”。但是我应该
class SomeClass:INotifyPropertyChanged
{
公共ObservableCollection项{get;set;}
公共字符串路径
{
get=>\u路径;
如果(_路径!=值){
_路径=值;
OnPropertyChanged(名称(路径));
//等待任务。运行(()=>长操作,例如加载某些项目使用“\u路径”);
}
}
属性不能是异步的,我认为它是“正常的”。但是我应该怎么做呢?
我认为这种情况经常发生。您可以使用
任务。在不使用等待的情况下运行。根据具体情况,它可能工作得很好,也可能工作得不好,这方面没有通用的答案
您可以创建这样的方法来设置值,这是一种更可靠的方法。但是,如果您需要数据绑定,则此方法无法工作:
public async Task SetPath(string value)
{
if (_path != value) {
_path = value;
OnPropertyChanged(nameof(Path));
await Task.Run(()=> ...);
}
如果您需要数据绑定并想使用await
,那么通常最好的做法是使用带计时器的去抖动-您不希望用户可以不受限制地使用一些昂贵的操作,以便冻结或崩溃应用程序。您可以使用任务。在不使用await
的情况下运行。这可能有效,也可能无效根据具体情况,关于这一点没有普遍的答案
您可以创建这样的方法来设置值,这是一种更可靠的方法。但是,如果您需要数据绑定,则此方法无法工作:
public async Task SetPath(string value)
{
if (_path != value) {
_path = value;
OnPropertyChanged(nameof(Path));
await Task.Run(()=> ...);
}
如果您需要数据绑定并希望使用wait
,那么通常最好使用带计时器的去抖动-您不希望用户可以不受限制地使用一些昂贵的操作,从而冻结或崩溃应用程序。您应该阅读Stephen Cleary关于异步数据绑定属性的MSDN文章他定义了一个名为NotifyTaskCompletion
的“任务观察者”类,该类实现了INotifyPropertyChanged
接口,并具有一个结果
属性,您可以绑定到:
异步编程:异步MVVM应用程序的模式:数据绑定:
public类主视图模型:INotifyPropertyChanged
{
公共字符串路径
{
获取{return\u path;}
设置
{
如果(_路径!=值)
{
_路径=值;
OnPropertyChanged(名称(路径));
AsyncProperty=new NotifyTaskCompletion(YourAsyncMethod());
}
}
}
公共NotifyTaskCompletion AsyncProperty{get;private set;}
}
您应该阅读Stephen Cleary关于异步数据绑定属性的MSDN文章,他在文章中定义了一个名为NotifyTaskCompletion
的“任务观察者”类,该类实现了INotifyPropertyChanged
接口,并具有一个结果
属性,您可以绑定到:
异步编程:异步MVVM应用程序的模式:数据绑定:
public类主视图模型:INotifyPropertyChanged
{
公共字符串路径
{
获取{return\u path;}
设置
{
如果(_路径!=值)
{
_路径=值;
OnPropertyChanged(名称(路径));
AsyncProperty=new NotifyTaskCompletion(YourAsyncMethod());
}
}
}
公共NotifyTaskCompletion AsyncProperty{get;private set;}
}
您可以插入property changed事件并执行异步任务。如果设置属性需要在后台启动长时间运行的方法,您应该考虑将其转换为方法并正确命名。我不希望出现这样的副作用。无论如何,如果值以快速顺序更改,会发生什么情况。您是否必须中止正在运行的任务?您也必须考虑一下。尝试将其移动到事件。例如,加载、用户事件或其他事件,并使该事件异步。您可以插入属性更改事件并执行异步任务。如果设置属性需要在后台启动长时间运行的方法,您应该d考虑将其转换为方法并正确命名。我不希望出现这样的副作用。无论如何,如果值以快速顺序更改会发生什么情况。您是否必须中止正在运行的任务?您也必须考虑这一点。尝试将其移动到事件。例如,加载、用户事件或其他事件,并使该事件异步是,我需要绑定的问题。如前所述,Task.Run-in-get本身不会导致任何问题。我将为使用计时器添加更多选项。是的,我需要绑定的问题。如前所述,Task.Run-in-get本身不会导致任何问题。我将为使用计时器添加更多选项。
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}"/>