【发布时间】:2011-03-22 17:20:07
【问题描述】:
WPF 应用有一个使用XamlReader.Load() 方法从单独的文件加载用户控件的操作:
StreamReader mysr = new StreamReader(pathToFile);
DependencyObject rootObject = XamlReader.Load(mysr.BaseStream) as DependencyObject;
ContentControl displayPage = FindName("displayContentControl") as ContentControl;
displayPage.Content = rootObject;
由于文件的大小,该过程需要一些时间,因此 UI 会冻结几秒钟。
为了保持应用响应,我尝试使用后台线程来执行不直接参与 UI 更新的部分操作。
尝试使用BackgroundWorker时出现错误:调用线程必须是STA,因为很多UI组件都需要这个
所以,我走了另一条路:
private Thread _backgroundThread;
_backgroundThread = new Thread(DoReadFile);
_backgroundThread.SetApartmentState(ApartmentState.STA);
_backgroundThread.Start();
void DoReadFile()
{
StreamReader mysr3 = new StreamReader(path2);
Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
(Action<StreamReader>)FinishedReading,
mysr3);
}
void FinishedReading(StreamReader stream)
{
DependencyObject rootObject = XamlReader.Load(stream.BaseStream) as DependencyObject;
ContentControl displayPage = FindName("displayContentControl") as ContentControl;
displayPage.Content = rootObject;
}
这没有解决任何问题,因为所有耗时的操作都保留在 UI 线程中。
当我这样尝试时,在后台进行所有解析:
private Thread _backgroundThread;
_backgroundThread = new Thread(DoReadFile);
_backgroundThread.SetApartmentState(ApartmentState.STA);
_backgroundThread.Start();
void DoReadFile()
{
StreamReader mysr3 = new StreamReader(path2);
DependencyObject rootObject3 = XamlReader.Load(mysr3.BaseStream) as DependencyObject;
Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
(Action<DependencyObject>)FinishedReading,
rootObject3);
}
void FinishedReading(DependencyObject rootObject)
{
ContentControl displayPage = FindName("displayContentControl") as ContentControl;
displayPage.Content = rootObject;
}
我遇到了一个异常:调用线程无法访问该对象,因为它拥有不同的线程。(在加载的 UserControl 中存在其他控件,它们可能会给错误)
有什么方法可以让 UI 响应式地执行此操作?
【问题讨论】:
-
使用后台工作者,确保如果你要修改(设置/添加)任何不在范围内的对象,而不是后台工作者所在的线程,你使用 func/可以解决的操作或委托,不要尝试在后台工作线程中设置它。如果有任何事情代替后台工作人员完成您的工作,完成后获取 OnComplete 事件/方法中的结果(e.result)并在 UI 线程中更新您的对象。
标签: c# wpf multithreading xamlreader