C# 属性更改时运行长操作

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路径”); } } 属性不能是异步的,我认为它是“正常的”。但是我应该

当我的属性引发PropertyChanged事件时,如何运行一些长操作? 例如:

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