【发布时间】:2016-12-29 02:37:09
【问题描述】:
我有一个属性绑定到我的视图的类。为了使我的视图保持最新,我实现了 INotifyPropertyChanged 并在每次某些属性更改时引发事件。
现在我有一些繁重的功能会冻结我的应用程序。我想把它们放到后台任务中。
首先:这是我目前的方法
(例如点击按钮)
private async void HeavyFunc()
{
foreach (var stuff)
{
count += await Task.Run(() => stuff.Fetch());
}
if (count == 0)
//...
}
东西类
public async Task<int> Fetch()
{
//network stuff
RaisePropertyChanged("MyProperty");
}
public async void RaisePropertyChanged(string pChangedProperty)
{
await Application.Current.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new ThreadStart(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pChangedProperty);
}
);
}
上面的代码给出了一个异常(“DependencySource”必须像“DependencyObject”一样在同一个线程中创建)。
AFAIK,您通常需要创建一个新线程并运行它(在等待它的同时)。 'await Task.Run(...);' 应该完成这项工作。
由于 PropertyChanged 事件直接影响 UI,在 UI 线程中调用它似乎是一个不错的决定。这就是我调用 Dispatcher.BeginInvoke 的原因。
我不明白:上面的异常是当不同的线程负责数据时引起的。但是我在我的 UI 线程上明确调用了该事件,并且该对象也应该由 UI 线程创建。那么为什么会出现异常呢?
我的主要问题是:我如何实现 INotifyPropertyChanged 接口的事件,以避免或处理上述大多数异步编程问题?构造函数时应该考虑什么?
【问题讨论】:
-
您在线程上引发 propertychanged 事件,因此如果它从未创建过 ui 元素,它将无法访问它们。
-
阅读this以真正了解ui线程与另一个线程执行的代码
-
属性本身是像位图一样的 DepedencyObject 吗?
标签: c# wpf asynchronous inotifypropertychanged