XamlReader.Load在后台线程。是否可以? [英] XamlReader.Load in a Background Thread. Is it possible?

查看:145
本文介绍了XamlReader.Load在后台线程。是否可以?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个WPF应用程序具有使用 XamlReader.Load()方法从单独的文件加载的用户控件的操作:

A WPF app has an operation of loading a user control from a separate file using XamlReader.Load() method:

StreamReader mysr = new StreamReader(pathToFile);
DependencyObject rootObject = XamlReader.Load(mysr.BaseStream) as DependencyObject;
ContentControl displayPage = FindName("displayContentControl") as ContentControl;
displayPage.Content = rootObject;



的过程需要一段时间,由于该文件的大小,因此使用者介面变得几秒钟冻结。

The process takes some time due to the size of the file, so UI becomes frozen for several seconds.

有关保持应用程序响应我尝试使用一个后台线程执行不直接在UI更新involed操作的一部分。

For keeping the app responsive I try to use a Background thread for performing the part of operation that is not directly involed in UI updating.

当尝试使用的BackgroundWorker 我得到了一个错误: 调用线程必须STA,因为许多UI组件都需要这个

When trying to use BackgroundWorker I got an error: The calling thread must be STA, because many UI components require this

所以,我去另一种方式:

So, I went another way:

 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线程。

This solves nothing because all time consuming operations remain in UI thread.

当我尝试这样,在后台使所有解析:

When I try like this, making all parsing in the background:

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;
  } 



我有一个例外: 调用线程不能访问此对象,因为不同的线程拥有它。(在加载的用户控件还有其他控件存在这可能会给错误)

I got an exception: The calling thread cannot access this object because a different thread owns it. (in the loaded UserControl there are other controls present which maybe give the error)

有任何方式来以这样的方式执行该操作的用户界面,以响应?

Is there any way to perform this operation in such a way the UI to be responsive?

推荐答案

获取XAML加载一个后台线程本质上是一个非首发。 WPF组件有螺纹亲和力并且通常来说,从它们被创建的线程唯一可用的。因此,装载在后台线程将会使UI响应,但创建一个则不能插入UI线程组件。

Getting the XAML to load an a background thread is essentially a non-starter. WPF components have thread affinity and are generally speaking only usable from the threads they are created one. So loading on a background thread will make the UI responsive but create components which then cannot be plugged into the UI thread.

在这里最好的办法是到XAML文件拆分成小块,并逐步加载它们在UI线程并确保允许在每之间的消息泵负荷运转。可能使用的BeginInvoke 调度对象调度负载。

The best option you have here is to break up the XAML file into smaller pieces and incrementally load them in the UI thread making sure to allow for a message pump in between every load operation. Possibly using BeginInvoke on the Dispatcher object to schedule the loads.

这篇关于XamlReader.Load在后台线程。是否可以?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆