首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WPF MVVM多线程问题

WPF MVVM多线程问题
EN

Stack Overflow用户
提问于 2010-10-07 21:19:40
回答 2查看 2.5K关注 0票数 0

我已经看到了其他类似于我的问题,但我没有看到任何我可以应用到使我的代码工作的问题。

所以我对MVVM很陌生,我正在尝试在后台线程中执行一些东西来更新我的UI。我注意到的是,第一次打开UI,后台线程第一次执行,如果集合是IEnumerable<>,则UI不会根据备份数据完全更新。如果集合为ObservableCollection<>,则会引发错误。

据我所读,对集合的更改需要在dispatcher线程上执行,但是OnPropertyChanged()调用不需要执行。有人,请告诉我这是怎么回事

我正在改变我的_Printers可观察的收藏:

代码语言:javascript
运行
复制
foreach (PrinterViewModel pv in _Printers)
            {
                DispatcherExec(() =>
                {
                var abilities = from x in _ServerData.Types
                                select new PrinterAbility(
                                    new PrintableType() { ID = x.ID, Name = x.Name, NumInProcUnit = x.NumInProcUnit, PrintersMappedTo = x.PrintersMappedTo, SysName = x.SysName },
                                    x.PrintersMappedTo.Contains(pv.Printer.ID)
                                    );


                    pv.Printer.SetAbilities(abilities);
                });

我的DispatcherExec看起来是这样的:

代码语言:javascript
运行
复制
 private void DispatcherExec(Action action)
    {
        //Dispatcher.Invoke((Action)delegate 
        //{
        //    action.BeginInvoke(null, null); 
        //}, null);
        Dispatcher.CurrentDispatcher.Invoke((Action)delegate
        {
            action.Invoke();
        }, null);
    }

下面是失败的SetAbilities代码:

代码语言:javascript
运行
复制
 public void SetAbilities(IEnumerable<PrinterAbility> abilities)
    {
        if (log.IsInfoEnabled)
            log.Info("SetAbilities(IEnumerable<PrinterAbility> abilities): called on printer "+Name);

        List<PrinterAbility> l = new List<PrinterAbility>();
        abilities.ForEach(i =>
            {
                i.PrinterAbilityChanged += new PrinterAbilityChangedEventHandler(OnPrinterAbilityChanged);
                l.Add(i);
            }
            );
        lock (_Abilities)
        {
            foreach (PrinterAbility pa in l)
                _Abilities.Add(pa);
        }
        if (log.IsDebugEnabled)
            log.Debug("SetAbilities(IEnumerable<PrinterAbility> abilities): leaving");
    }

在_Abilities.Add(pa)可观察的集合中,添加它说:“这种类型的CollectionView不支持从不同于Dispatcher线程的线程更改其SourceCollection。”我在想,“你在开玩笑吗?”

此外,我认为对可观察集合中的对象的更改会自动使其调用OnCollectionChanged(),对吗?

提前谢谢各位。

EN

Stack Overflow用户

发布于 2010-10-07 21:41:01

对于后台线程,您应该使用与任何WPF控件相关联的Dispatcher,而不是Dispatcher.CurrentDispatcher。

也是

代码语言:javascript
运行
复制
Dispatcher.CurrentDispatcher.Invoke((Action)delegate
        {
            action.Invoke();
        }, null);

是多余的,应该是

代码语言:javascript
运行
复制
wpfDispatcher.Invoke(action, null);

最后,对于第一个块,您通常应该避免将循环变量传递给lambdas,使用临时赋值技巧来绕过这些狡猾的闭包问题。不过,几乎可以肯定的是,这不是问题所在。

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3885962

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档