WPF 具有跨线程功能的UI元素

概括

VisualTarget 本身继承自 CompositionTarget,而不是 Visual;其本身并不是可视化树的一部分。但是它的构造函数中可以传入一个 HostVisual 对象,这个对象是一个 Visual,如果将此 HostVisual 放入原 UI 线程的可视化树上,那么 VisualTarget 就与主 UI 线程连接起来了。

另外一半,VisualTarget 需要连接另一个异步线程的可视化树。然而,VisualTarget 提供了 RootVisual 属性,直接给此属性赋一个后台 UI 控件作为其值,即连接了另一个 UI 线程的可视化树。

代码:

cs 复制代码
 /// <summary>
 /// 此控件具有跨线程更新功能
 /// </summary>
 public class DispatcherContainer : UIElement
 {
     /// <inheritdoc />
     public DispatcherContainer()
     {

         ThreadUpdate();
     }

     public void ThreadUpdate()
     {
         var thread = new Thread(() =>
         {
             _visualTarget = new VisualTarget(_hostVisual);
             DrawingVisual drawingVisual = new DrawingVisual();
             var drawing = drawingVisual.RenderOpen();
             using (drawing)
             {
                 var text = new FormattedText("欢迎访问",
                     CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
                     new Typeface(new FontFamily("微软雅黑"), new FontStyle(), FontWeight.FromOpenTypeWeight(1),
                         FontStretch.FromOpenTypeStretch(1)), 20, Brushes.DarkSlateBlue);

                 drawing.DrawText(text, new Point(100, 100));
             }

             var containerVisual = new ContainerVisual();

             containerVisual.Children.Add(drawingVisual);

             _visualTarget.RootVisual = containerVisual;


            

             System.Windows.Threading.Dispatcher.Run();
         });




         thread.SetApartmentState(ApartmentState.STA);
         thread.Start();
     }

     /// <inheritdoc />
     protected override Visual GetVisualChild(int index)
     {
         return _hostVisual;
     }

     /// <inheritdoc />
     protected override int VisualChildrenCount => 1;

     private readonly HostVisual _hostVisual = new HostVisual();
     private VisualTarget _visualTarget;
 }

使用:

解释:

先理解Host 和 Root含义:

Host是宿主,Root是根基,大概是Root可以放在Host里面,Host是Root的载体的意思;

VisualTarget 的解释:提供跨线程边界将一个可视化树连接到另一个可视化树的功能。

拆分理解一下:提供了 跨线程的(副词) 连接可视化树(动词) 的功能。

简单理解为:可以跨线程拼接UI元素

与主线程连接:

上述控件的_hostVisual 字段属于主线程(UI 线程)的可视化树上,创建_visualTarget实例,把【DispatcherContainer 的_hostVisual 字段】赋值给【_visualTarget私有的_hostVisual字段】;

代码表现为:

cs 复制代码
 _visualTarget = new VisualTarget(_hostVisual);

即_visualTarget通过关联了_hostVisual 间接的关联了UI线程;

与子线程连接:

//创建可视化对象,添加由DrawingVisual绘制的内容

var containerVisual = new ContainerVisual();

containerVisual.Children.Add(drawingVisual);

//关联_visualTarget和子线程的可视化树

_visualTarget.RootVisual = containerVisual;

即_visualTarget通过关联了【子线程创建的containerVisual】间接的关联了子线程;

AI分析:

在 WPF 的 VisualTarget 中,_hostVisualRootVisual 之间的关系是跨线程可视化的桥梁。让我详细解释它们的关系:

架构关系

复制代码
主线程 (UI Thread)
│
├── HostVisual (_hostVisual)
│   └── 作为占位符嵌入主可视化树
│
└── 通过 VisualTarget 连接到 ↓

后台线程 (STA Thread)
│
├── VisualTarget (_visualTarget)
│   └── 连接到主线程的 HostVisual
│       └── RootVisual (容器视觉)
│           └── 实际的可视化内容(文字、图形等)

详细关系说明

1. HostVisual (_hostVisual) - 主线程

  • 角色:在主可视化树中的"占位符"或"代理"

  • 位置:位于主 UI 线程的可视化树中

  • 作用:为跨线程的可视化内容提供一个连接点

2. VisualTarget - 跨线程连接器

  • 角色:连接不同线程间可视化树的桥梁

  • 构造new VisualTarget(_hostVisual) 建立与 HostVisual 的连接

  • 作用:管理线程间的可视化数据传递

3. RootVisual - 后台线程的根

  • 角色:后台线程可视化树的根节点

  • 位置:位于后台线程的可视化树中

  • 作用:包含实际要显示的可视化内容

总结

其他文章展示的代码大同小异,思想就是一个HostVisual 对象A 在主线程可视化树上,然后有一个子线程的UI对象B ,然后A 关联VisualTarget 对象的一个字段:_hostVisual ,B关联VisualTarget 对象的一个属性:RootVisual,实现B替换A的效果;

引用:

https://lindexi.blog.csdn.net/article/details/103184442?fromshare=blogdetail&sharetype=blogdetail&sharerId=103184442&sharerefer=PC&sharesource=qq_59062726&sharefrom=from_link

https://www.cnblogs.com/walterlv/p/10236528.html

https://blog.csdn.net/amanda_zhang2010/article/details/68946798?fromshare=blogdetail&sharetype=blogdetail&sharerId=68946798&sharerefer=PC&sharesource=qq_59062726&sharefrom=from_link

https://www.cnblogs.com/Zhouyongh/archive/2011/01/12/1933414.html

一点个人浅见,未必周全,权当抛砖引玉。若有疏漏之处,还请大家一起指正讨论。

相关推荐
Chris _data18 小时前
c#学习WPF笔记(一)
学习·c#·wpf
FuckPatience1 天前
WPF 自定义容器控件的布局
wpf
逆境不可逃1 天前
深入理解 SingleFlight:从单机到分布式的请求合并方案全解析
分布式·wpf
TDengine (老段)1 天前
TDengine 逻辑计划生成 — 从 AST 到关系代数算子树
大数据·数据库·物联网·wpf·时序数据库·tdengine·涛思数据
小二·3 天前
微服务架构设计与实践
微服务·架构·wpf
暖馒3 天前
WPF-Prism学习入门步骤记录
学习·wpf
baivfhpwxf20233 天前
雷赛(Leadshine)EtherCAT 数字 I/O 模块(如 EMC-E5064-8)的状态指示灯(I/O 状态)说明
c#·wpf
故渊at3 天前
第二板块:Android 四大组件标准化学理 | 第十二篇:四大组件全景总结与系统服务(System Server)架构
android·架构·wpf·四大组件·system service
伶俜664 天前
# [特殊字符] 零基础学 ArkUI 数据持久化(专题三):5 种存储方案深度对比
学习·华为·wpf·harmonyos
IT策士4 天前
Redis 从入门到精通:数据结构String 与键管理
数据结构·redis·wpf