我正在实现一个
UI
,其中包含我使用 framework MVVMCross
的列表。为了填充列表,我迭代了几个目录以收集特定的XML documents
。现在我想在不同的线程中外包这个迭代过程,以防止主窗口冻结并显示加载轮或进度条。如果我启动这个函数,我会得到Exception
,我必须从调度程序线程启动线程,但在我看来,我已经从调度程序线程启动它。我做错了什么?
readonly Dispatcher _dispatcher;
public HomeViewModel(IMvxNavigationService navigationService)
{
NavigationService = navigationService;
_dispatcher = Dispatcher.CurrentDispatcher;
}
private async void StartDispatcher()
{
BackgroundWorker _backgroundWorker = new BackgroundWorker();
_backgroundWorker.DoWork += _backgroundWorker_DoWork;
Delegate action = new Action(_backgroundWorker.RunWorkerAsync);
await _dispatcher.BeginInvoke(action, DispatcherPriority.Normal);
}
private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
LoadingProcess();
}
尝试了多种方法来使用调度程序启动线程,但没有任何效果。
在后台工作的典型方式是:
private async void OnSomeTypeOfEvent()
{
var progress = new Progress<long>(); // optional
var cts = new CancellationTokenSource(); // optional
try{
var result = await Task.Run(() => DoWorkInBackground(progress, cts.Token));
// Update the UI with the result
}
catch(OperationCancelledException){} // ignore
catch(Exception e){
// handle failure
}
}
private TResult DoWorkInBackground(IProgress progress, CancellationToken cancel){
// Do background work work
}
所有带有取消和进度的内容都是可选的,并且要求您有一些控制来报告进度和取消。
您尝试做的事情毫无意义。如果您要求调度程序运行某些内容,它会在 UI 线程上运行它,因此它仍然会阻塞 UI。调度程序的主要目的是当您在后台线程上运行某些内容并且需要在 UI 线程上运行某些内容时。但是,我建议使用异步/等待模式,因为这往往会使代码更易于阅读和理解。
您需要确保
DoWorkInBackground
是线程安全的,并且在没有适当同步的情况下不要使用任何共享的、可变的数据结构。如果可能的话,尽量保持方法“纯粹”。