Поэтому я хочу загрузить свои коллекции данных в фоновом потоке, а затем связать свое древовидное представление с новой коллекцией (вместо того, чтобы помещать вещи в очередь фонового потока в диспетчере каждый раз, когда он хочет добавить элемент в список [звучит неэффективно]) .
Это возможно? Я создаю новую структуру данных, и она выводится как pd.result в фоновом потоке. Когда поток пользовательского интерфейса проверяет, закрыто ли диалоговое окно, он должен затем установить
ModuleHierarchyVM.TopLevelModules = pd.Result as ObservableCollection<ModuleViewModel>;
после этого вызывается событие OnLoadVCD. У меня есть обработчик событий, который затем пытается установить источник элементов древовидного представления для новой коллекции.
this.AvailableModulesTreeView.ItemsSource = gvvm.ModuleHierarchyVM.TopLevelModules;
Это приводит к сбою с ошибкой: «Вызывающий поток не может получить доступ к этому объекту, потому что им владеет другой поток».
Даже не зная, как его отлаживать, стек вызовов не дает никаких реальных подробностей.
Однако, если я просто установлю для Itemsource пустую новую пустую коллекцию, например:
this.AvailableModulesTreeView.ItemsSource = (IEnumerable<object>)new List<object>();
он не вылетает (но и мои данные тоже не отображаются). Есть идеи, что могло вызвать сбой?
Я подумал, что, возможно, я обновляю пользовательский интерфейс из неправильного потока, поэтому я попытался вызвать диспетчер с помощью begininvoke и проверить, действительно ли я являюсь потоком пользовательского интерфейса с помощью dispatcher.checkaccess (). так что, похоже, проблема не в этом. Однако я действительно не знаю, что происходит.
Другой способ, которым я мог бы реализовать это, - просто заставить мою процедуру синтаксического анализа просто обновлять исходную структуру данных, которая привязана к древовидной структуре, вызывая диспетчер для каждого элемента, когда он добавляется в наблюдаемую коллекцию. Однако, даже если это единственное решение, мне действительно не нравится не знать, почему что-то не работает. На мой взгляд, разумно просто создать совершенно новую структуру данных в другом потоке, а затем заново привязать новую структуру данных к древовидной структуре, отбросив старую. Мне это также кажется чище, чем десятки однострочных вызовов ObservableCollectionInstance.Add, размещаемых в диспетчере во время синтаксического анализа файла в фоновом потоке.
Полный код:
метод, вызываемый потоком пользовательского интерфейса
public bool LoadPortInterface(string VCDFileName)
{
ProgressDialog pd = new ProgressDialog("Loading File: ", VCDFileName);
pd.Owner = Application.Current.MainWindow;
pd.WindowStartupLocation = WindowStartupLocation.CenterOwner;
ModuleHierarchyVM.TopLevelModules.Clear();
VCDData TempVCDOutput = null;
Func<object> handler = delegate
{
return VCDParser.ParseVCDFileForAllPorts(VCDFileName, this, pd.Worker, out TempVCDOutput);
};
pd.RunWorkerThread(handler);
pd.ShowDialog();
if (pd.DialogResult == true)
{
ModuleHierarchyVM.TopLevelModules = pd.Result as ObservableCollection<ModuleViewModel>;
VCDOutput = TempVCDOutput;
}
OnLoadVcd();
}
Ответ на обработчик события OnLoadVCD в графическом средстве просмотра:
void gvvm_LoadVCDEvent(object sender, EventArgs e)
{
this.AvailableModulesTreeView.ItemsSource = gvvm.ModuleHierarchyVM.TopLevelModules;
}