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.

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.

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

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?

8
задан rem 22 March 2011 в 17:20
поделиться