C# 此类型的CollectionView不支持从线程更改其SourceCollection。。。在使用调度程序时?
因此,我正在开发一个带有UI的插件,该UI在应用程序(主应用程序)中使用。要使我的UI在主应用程序运行时具有响应性,我将在其单独的线程中启动UI,如下所示:C# 此类型的CollectionView不支持从线程更改其SourceCollection。。。在使用调度程序时?,c#,wpf,multithreading,mvvm-light,dispatcher,C#,Wpf,Multithreading,Mvvm Light,Dispatcher,因此,我正在开发一个带有UI的插件,该UI在应用程序(主应用程序)中使用。要使我的UI在主应用程序运行时具有响应性,我将在其单独的线程中启动UI,如下所示: public void ShowDialog(IIFCConverter ifcConverter) { thread = new Thread(x => { thread.Name = "UI-thread"; window = ne
public void ShowDialog(IIFCConverter ifcConverter)
{
thread = new Thread(x =>
{
thread.Name = "UI-thread";
window = new MainWindow();
var mainViewModel = ServiceLocator.Current.GetInstance<MainWindowViewModel>();
mainViewModel.SetIFCConverter(x as IIFCConverter);
ViewModelLocator.MainWindow = window;
window.ShowDialog();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start(ifcConverter);
}
private void AddNewFile(AddNewFileMessage obj)
{
if (!(obj.Sender is ButtonViewModel)) return;
if (string.IsNullOrEmpty(obj.Path)) return;
var ifcFileViewModel = new IFCFileViewModel(new Common.Model.IFCFile { Path = obj.Path, Active = true });
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
try
{
ListBoxItems.Insert(ListBoxItems.Count - 1, ifcFileViewModel);
}
catch(Exception ex)
{
}
});
当我使用MVVM light的DispatcherHelper时,我得到了这个结果。
我曾尝试使用“普通”调度器来进行调度,但这给了我相同的结果
首先,我很想知道它为什么这样做的机理?
我已经检查了我的线程,我可以看到OnCollectionChanged是从我的UI线程调用的。
我似乎找不到第一次运行(运行正常)和后续运行之间的线程结构有任何差异
第二,我能做些什么
我测试过但没有帮助的东西:
public void ShowDialog(IIFCConverter ifcConverter)
{
thread = new Thread(x =>
{
thread.Name = "UI-thread";
window = new MainWindow();
var mainViewModel = ServiceLocator.Current.GetInstance<MainWindowViewModel>();
mainViewModel.SetIFCConverter(x as IIFCConverter);
ViewModelLocator.MainWindow = window;
window.ShowDialog();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start(ifcConverter);
}
private void AddNewFile(AddNewFileMessage obj)
{
if (!(obj.Sender is ButtonViewModel)) return;
if (string.IsNullOrEmpty(obj.Path)) return;
var ifcFileViewModel = new IFCFileViewModel(new Common.Model.IFCFile { Path = obj.Path, Active = true });
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
try
{
ListBoxItems.Insert(ListBoxItems.Count - 1, ifcFileViewModel);
}
catch(Exception ex)
{
}
});
}然而,我觉得这很难看,并希望避免它,为什么这甚至工作?当我把我所有的动作都放在try-Catch块中时,一切似乎都很好 看一看并阅读以下主题:。好的,所以我找到了真正的问题。 viewmodel确实是在与我的插件UI相同的线程上创建的 但是:我使用MVVMLight工具包中可用的Messenger来处理viewmodels之间的通信,当我的窗口关闭时,我忘记注销viewmodel。因此,第二次打开窗口时,我开始在viewmodels之间发送消息。第一个viewmodel出现反应,这就是问题的原因。 这也是try-Catch块起作用的原因,因为有来自正确线程的第二个调用正在起作用。 我在viewmodel的构造函数中添加了一个datetime,实际上调用了两个不同的viewmodel。我不明白为什么我会得到那个例外。如果有的话,第一个viewmodel应该通过datacontext连接到第一个视图。这就像视图连接到了两个不同ViewModel的事件一样
不管怎样,它现在起作用了:当我的窗口关闭时,我只是从消息服务中注销viewmodel,它就像一个符咒 我假设ListBoxITems属于默认UI线程,而不是派生的STA线程。也许CheckBeginInvokeOnUI被你的线程愚弄了,并试图在你自己的线程上而不是在它的所有者上访问集合。从我可以看到你的
ViewModel
是由一个不是UI的线程创建的。更改此选项,您的解决方案将与任何一个调度器一起工作。@XAMlMAX,您如何看待这一点?从踏板窗口?还是仅仅因为我得到了例外?ViewModel应由IoC容器创建,IoC容器由窗口中使用的资源字典创建。我看不出这是如何在错误的线程上创建的。。。我看不出如何以不同的方式来实现它…var mainViewModel=ServiceLocator.Current.GetInstance()代码>是在UI线程
中创建的,这与调用线程不同,因此对象是由不同的线程创建的,您怎么能看不到这一点?那么您将无法从任何其他线程与窗口交互,因此我想这在您的场景中是毫无意义的。在线程B上创建的窗口永远无法从线程A访问。