我有一个从数据库加载数据的详细视图(用于列表选择),我不想通过将数据库逻辑从UI线程移开来避免任何阻塞。
的问题:
如何使用WPF执行此操作?如果没有内置的方法,我的想法就是为它创建一个类,并将它用于viewmodel中的这些加载方法。例如。想到两个变体的伪代码
public class ViewModelBackgroundLoader<TInput, TResult>
{
public ViewModelBackgroundLoader(Func<TInput, CancellationToken, TResult> loadFunc, Action<TResult> uiContinuation)
{
}
public void Load(TInput input)
{
// set cancellation for previous loadFunc
// async await loadAction on threadpool thread
// If not cancelled...
// uiContinuation() on UI thread
}
}
public class ViewModelBackgroundLoadedProperty<TInput, TResult> : INotifyPropertyChanged
{
public ViewModelBackgroundLoadedProperty(Func<TInput, CancellationToken, TResult> loadFunc)
{
}
public TInput Input
{
set
{
// set cancellation for running loadFunc
// async await loadAction on threadpool thread
// If not cancelled...
// Update Result property and fire propertychanged (in UI thread)
}
}
public TResult Result { get; }
}
答案 0 :(得分:0)
如果您使用我编写的名为NotifyTask<T>
的辅助类:
public class ViewModel<TInput, TResult>
{
private CancellationTokenSource _cts;
public NotifyTask<TResult> Operation { get; private set; }
public void Load(TInput input)
{
if (_cts != null)
_cts.Cancel();
_cts = new CancellationTokenSource();
Operation = NotifyTask.Create(loadFunc(input, _cts.Token));
}
}
可以对Operation.Result
进行数据绑定(还有其他数据绑定属性可以轻松显示/隐藏加载指示符等)。
如您所述CancellationTokenSource
,取消之前的操作(如果有的话)。没有必要显式检查并避免旧操作的UI更新,因为Operation
一旦新的启动就会被覆盖(因此永远不会显示旧数据 - 即使未被取消,也只会被忽略)。