我有一个类,其中的属性与我的视图绑定。为了保持视图的最新状态,我实现了INotifyPropertyChanged,并在每次属性更改时引发事件。
现在我有一些耗费大量时间的函数会冻结我的应用程序。我想将它们放入后台任务中。
首先,这是我的当前方法(例如,点击按钮)。
上面的代码抛出了一个异常("DependencySource"必须在与"DependencyObject"相同的线程中创建)。
据我所知,通常需要创建一个新的线程并运行它(同时等待它)。 ´await Task.Run(...);´ 应该可以完成这个工作。
由于PropertyChanged事件直接影响UI,因此在UI线程中调用它似乎是一个好决定。这就是为什么我调用了Dispatcher.BeginInvoke。
我不明白的是:上述异常是由于不同的线程负责数据导致的。但是我明确地在我的UI线程上调用了事件,对象也应该由UI线程创建。那么为什么会出现异常呢?
我的主要问题是:如何通常实现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"相同的线程中创建)。
据我所知,通常需要创建一个新的线程并运行它(同时等待它)。 ´await Task.Run(...);´ 应该可以完成这个工作。
由于PropertyChanged事件直接影响UI,因此在UI线程中调用它似乎是一个好决定。这就是为什么我调用了Dispatcher.BeginInvoke。
我不明白的是:上述异常是由于不同的线程负责数据导致的。但是我明确地在我的UI线程上调用了事件,对象也应该由UI线程创建。那么为什么会出现异常呢?
我的主要问题是:如何通常实现INotifyPropertyChanged接口的事件以避免或处理大多数异步编程问题,例如上面的问题?构建函数时应考虑什么?