Приложение 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;
Процесс занимает некоторое время из-за размера файла, поэтому пользовательский интерфейс останавливается на несколько секунд.
Для поддержания отзывчивости приложения я пытаюсь использовать фоновый поток для выполнения той части операции, которая не вызывается напрямую при обновлении пользовательского интерфейса.
При попытке использовать BackgroundWorker
я получил ошибку: Вызывающий поток должен быть STA, поскольку для многих компонентов пользовательского интерфейса требуется это
Итак, я пошел другим путем:
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;
}
Это ничего не решает, потому что все трудоемкие операции остаются в потоке пользовательского интерфейса.
Когда я пытаюсь так сделать, все разбора в фоновом режиме:
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 присутствуют другие элементы управления, которые могут выдавать ошибку)
Есть ли способ выполнить эту операцию таким образом, чтобы интерфейс реагировал?