Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 此类型的CollectionView不支持从线程更改其SourceCollection。。。在使用调度程序时?_C#_Wpf_Multithreading_Mvvm Light_Dispatcher - Fatal编程技术网

C# 此类型的CollectionView不支持从线程更改其SourceCollection。。。在使用调度程序时?

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

因此,我正在开发一个带有UI的插件,该UI在应用程序(主应用程序)中使用。要使我的UI在主应用程序运行时具有响应性,我将在其单独的线程中启动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)
    {

    }
});
当我使用MVVM light的DispatcherHelper时,我得到了这个结果。 我曾尝试使用“普通”调度器来进行调度,但这给了我相同的结果

首先,我很想知道它为什么这样做的机理? 我已经检查了我的线程,我可以看到OnCollectionChanged是从我的UI线程调用的。 我似乎找不到第一次运行(运行正常)和后续运行之间的线程结构有任何差异

第二,我能做些什么

我测试过但没有帮助的东西:

  • 我使用MVVM light的IoC容器,并将其注册为LocatorProvider,但每次初始化UI并将该实例设置为LocatorProvider时,我都会创建一个新的IoC容器
  • 我正在初始化窗口构造函数中的DispatcherHelper。所以应该在正确的螺纹上
  • 真正有效的方法是将动作包装在try-Catch块中,如下所示:

        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访问。