报错:System.Windows.Markup.XamlParseException:必须在与 DependencyObject 相同的线程上创建 DependencySource。【2021年2月1日】

Start

一个打工仔在日常板砖的时候,有一个TreeView,需要向其使用“异步”的方法添加节点。首先绑定 ItemSource 是自定义的Node类的集合 ObservableCollection Nodes,其属性 string 类型的 Text 和 Brush 类型的 Color。

裂开!必须在与 DependencyObject 相同的线程上创建 DependencySource

我使用await、async 报错必须在 依赖属性 相同的线程上创建 依赖源???
这明显是,我在子线程中操作了UI啊。当我看到 依赖源——Source的时候,我第一想到的就是 Nodes ? 我在异步中操作了Nodes的集合嘛,这个问题百度上有十万个贴子都可以解决,本想着随便开一个就可以解决了。emmmm 列出两个吧。

one. await async

var list = await Task.Run(() =>
{
  List<Node> list = new List<Node>();
  list.Add(...);

  return list;
});
Nodes = new ObservableCollection<Node>(list);

two.

Task.Factory.StartNew(() => 
{
  //导致UI卡住的代码
  List<Node> list = new List<Node>();
  list.Add(...);
  
  Application.Current.Dispatcher.Invoke(new Action(()=>
  {
       //回到主线程操作
       Nodes = new ObservableCollection<Node>(list);
  }));
});

还有很多自行百度就好了,随便一查就有的
然后我边查百度,边试代码,头都炸了。结果还是一样
算了。二分删除大法,这。。。。。

两天后

实在是找不到问题出在哪里了,后来想起来公司大佬告诉我的一个工具 某Spy 动态调试exe源码。然后我一步一步执行发现崩溃的地方在这里

程序集System.Windows.FrameworkTemplate
private void LoadTemplateXaml(System.Xaml.XamlReader templateReader, XamlObjectWriter currentWriter)

看函数名 加载XAML模板?(没有注释具体干啥的期待评论区大佬出现)
我重新检查了一下TreeView的ItemsTempLate,好像也没什么问题

<TextBlock VerticalAlignment="Center">
                <Run Foreground="Black" Text="{Binding Text}" />
                <Run Foreground="{Binding Color}" Text="{Binding Text}" />
 </TextBlock>

最后通过二分查找法找到 是 Color 的问题。由于 Node 在异步操作中创建,那么属性Color也会在异步中创建。所以报跨线程的错误就没什么奇怪的了。
可是为什么 Text 在异步中赋值没问题。而 Brush 的 Color 就不行?

群里大佬:

关关菜机 2021-1-31 23:06:48
你转换器产生的是新实例

关关菜机 2021-1-31 23:07:17
不是原有实例的属性新值

关关菜机 2021-1-31 23:08:09
你的color应该是string类型而不是brush类型

关关菜机 2021-1-31 23:08:41
通过值转换器实现字符转brush

关关菜机 2021-1-31 23:09:47
用存在线程安全的类实例去实现跨线程功能,没准就是你报错的原因

END

这波还是比较亏,由于Node类中 Text 属性没问题,就误导我忽视掉了 Color 属性。白白查了几天百度 我丢
以前的经理跟我说的,百度能解决 99% 的问题。剩下的 1% 要么,是你的东西在技术顶尖了 没有资料。剩下的就是你的问题的方向错了。显然我没有那么 diǎo 属于后者。
posted @ 2021-02-01 18:39  神奇玩偶obbb  阅读(1070)  评论(0)    收藏  举报