1. 渲染系统概述

WPF 采用保留模式渲染系统 (Retained Mode Rendering System),该系统可分为 UI 线程和复合线程两个主要部分,两者协作完成 WPF 应用程序的渲染工作。

1.1. 立即模式GUI和保持模式GUI

图形 API 可分为保留模式API 和即时模式API。 Direct2D 是一种即时模式 API。 WPF 是保留模式 API 的一个示例。

1.1.1. 立即模式GUI

保留模式 API 是声明性的。 应用程序从图形基元(如形状和线条)构造场景。 图形库将场景的模型存储在内存中。 为了绘制帧,图形库将场景转换为一组绘图命令。 在帧之间,图形库将场景保留在内存中。 若要更改呈现的内容,应用程序会发出命令来更新场景,例如添加或删除形状。 然后,该库负责重绘场景。
每渲染一帧时(很多机器都可以做到1秒钟60帧),渲染库需要执行渲染每个元素的指令,所以这种库无需记住你已经渲染了什么东西,反正每次都会全部重绘。会持续消耗你的CPU和GPU资源。
即时模式的GUI库常用于更动态的元素表现,比如实时图表,动画,特效,游戏等,任何一个像素的改变,都会快速的呈现给你的用户。

1.2.2. 保持模式GUI

即时模式 API 是过程性的。 每次绘制新帧时,应用程序都会直接发出绘图命令。 图形库不会在帧之间存储场景模型。 相反,应用程序会跟踪场景。
由开发者调用渲染库的API,适时的重绘需需要改变的元素。这就需要渲染库有能力记住之前都渲染了什么东西,所以也会占用更多的内存。
保留模式的GUI库通常更容易使用,使开发更快,但它们也通常也会需要更多的开销,比如要记住元素的位置、层级、遮盖情况等等。
保留模式 API 可能更易于使用,因为 API 会为你执行更多工作,例如初始化、状态维护和清理。 另一方面,它们通常不太灵活,因为 API 施加了自己的场景模型。 此外,保留模式 API 可能具有更高的内存要求,因为它需要提供通用场景模型。 使用即时模式 API,可以实现有针对性的优化。

2. 线程模型

2.1. 概述

WPF 应用程序有两类线程负责渲染:一个用于管理 UI 叫 UI 线程,另一个用于处理渲染叫复合线程,也叫呈现线程。 当 UI 线程接收输入、处理事件、绘制屏幕和运行应用程序代码时,复合线程通过隐藏方式在后台高效运行。

2.1.1. UI线程

UI 线程是 WPF 应用程序最重要的线程。它负责处理所有用户交互事件,如按钮单击、菜单选择以及键盘和鼠标输入。它还负责计算 UI 元素的布局、处理数据绑定、触发属性更改等工作。UI 线程是单线程的,这意味着在同一时间只能有一个操作在 UI 线程上运行。
UI 线程在称为 Dispatcher 的对象内对工作项进行排队。 Dispatcher 基于优先级选择工作项,并运行每一个工作项直到完成。 每个 UI 线程必须具有至少一个 Dispatcher,且每个 Dispatcher 都可精确地在一个线程中执行工作项。
UI 线程也可以启用多个,由于多线程程序既复杂又难以调试,因此当存在单线程解决方案时,应避免使用多线程程序。
UI 线程的主要职责是:
  1. 计算布局和测量视觉(Visual)对象。
  2. 实现数据绑定和依赖属性系统。
  3. 处理用户输入和事件。
  4. 安排和分派渲染工作项给复合线程。
总的来说,UI 线程的工作是计算最终结果,并安排复合线程执行渲染工作。

2.1.2. 复合线程

复合线程负责 WPF 视觉层次结构的实际渲染工作。当应用程序的 UI 需要在屏幕上重新绘制时,复合线程就会介入,包括窗口大小调整、动画以及任何影响 UI 外观的操作。
复合线程与 UI 线程紧密协作。UI 线程计算布局并安排 Visual 对象,复合线程会渲染 Visual 对象,并将其发送给桌面窗口管理器以在屏幕上显示。
复合线程是一个线程池,包含若干个工作线程,线程数量通常与系统的 CPU 内核数量相同,可以在多个内核上并行工作,从而提高 WPF 应用程序 UI 操作的性能。
复合线程的主要职责是:
  1. 生成可视化树中元素的位图。
  2. 应用效果(如3D变换、混合模式等)。
  3. 合成最终的渲染内容发送给桌面窗口管理器。

2.2. UI线程和复合线程协作

UI 线程和复合线程是 WPF 渲染系统的两个重要部分,它们相互协作完成渲染工作:
  1. UI线程负责计算布局、测量元素大小、响应用户交互等。
  2. UI线程通过 VisualTarget.Render 方法将渲染工作项分派给复合线程线程池。
  3. 复合线程中的工作线程并行执行渲染工作,生成位图数据。
  4. 复合线程将最终的渲染结果提交给桌面窗口管理器显示。

3. 性能优化

若要生成响应迅速、用户友好的应用程序,诀窍在于通过保持工作项小型化来最大化 Dispatcher 吞吐量。 这样一来,工作项就不会停滞在 Dispatcher 队列中,因等待处理而过时。 输入和响应间任何可察觉的延迟都会让界面卡顿无响应,带来糟糕体验。
需要注意的是,UI线程不应该执行长时间的操作,否则会导致UI无响应。相反,应该在后台线程上执行这些任务。
WPF 应用程序在处理大型操作时,如涉及大型计算,或需要查询某些远程服务器上的数据库。通常情况下,解决方法是在单独的线程中处理大型操作,让 UI 线程更多倾向于处理 Dispatcher 队列中的工作项。大型操作完成后,再通过 Dispatcher 将结果发送到 UI 线程进行安全渲染。
总的来说,UI 线程专注于用户交互和布局,而复合线程专注于高效呈现 UI。通过正确地利用这两个线程,可以构建响应灵敏且高效的 WPF 应用程序。
 
 

WPF线程模型的更多相关文章

  1. WPF 线程:使用调度程序构建反应速度更快的应用程序

    原文:WPF 线程:使用调度程序构建反应速度更快的应用程序 作者:Shawn Wildermuth 原文:http://msdn.microsoft.com/msdnmag/issues/07/10/ ...

  2. WPF QuickStart系列之线程模型(Thread Model)

    这篇博客将介绍WPF中的线程模型. 首先我们先来看一个例子,用来计算一定范围内的素数个数. XAML: <Grid> <Grid.RowDefinitions> <Row ...

  3. 编写高质量代码改善C#程序的157个建议——建议87:区分WPF和WinForm的线程模型

    建议87:区分WPF和WinForm的线程模型 WPF和WinForm窗体应用程序都有一个要求,那就是UI元素(如Button.TextBox等)必须由创建它的那个线程进行更新.WinForm在这方面 ...

  4. WPF的线程模型

    原文:WPF的线程模型 WPF的线程模型            周银辉 谈到多线程,很多人对其可能都不太有好感,觉得麻烦与易出错.所以我们不排除有这样的情况:假设我对“多线程”.“异步”这些字眼潜意识 ...

  5. 看我是如何处理自定义线程模型---java

    看过我之前文章的园友可能知道我是做游戏开发,我的很多思路和出发点是按照游戏思路来处理的,所以和web的话可能会有冲突,不相符合. 来说说为啥我要自定义线程模型呢? 按照我做的mmorpg或者mmoar ...

  6. HBase的Write Ahead Log (WAL) —— 整体架构、线程模型

    解决的问题 HBase的Write Ahead Log (WAL)提供了一种高并发.持久化的日志保存与回放机制.每一个业务数据的写入操作(PUT / DELETE)执行前,都会记账在WAL中. 如果出 ...

  7. Netty学习三:线程模型

    1 Proactor和Reactor Proactor和Reactor是两种经典的多路复用I/O模型,主要用于在高并发.高吞吐量的环境中进行I/O处理. I/O多路复用机制都依赖于一个事件分发器,事件 ...

  8. Mina、Netty、Twisted一起学(十):线程模型

    要想开发一个高性能的TCP服务器,熟悉所使用框架的线程模型非常重要.MINA.Netty.Twisted本身都是高性能的网络框架,如果再搭配上高效率的代码,才能实现一个高大上的服务器.但是如果不了解它 ...

  9. servlet的生命周期与运行时的线程模型

    第 14 章 生命周期 注意 讲一下servlet的生命周期与运行时的线程模型,对了解servlet的运行原理有所帮助,这样才能避免一些有冲突的设计. 如果你不满足以下任一条件,请继续阅读,否则请跳过 ...

  10. eventloop & actor模式 & Java线程模型演进 & Netty线程模型 总结

    eventloop的基本概念可以参考:http://www.ruanyifeng.com/blog/2013/10/event_loop.html Eventloop指的是独立于主线程的一条线程,专门 ...

随机推荐

  1. AI自动生成视频保姆级教程,还能赚包辣条哦~

    友友们,小卷今天给大家分享下如何通过AI自动生成视频,只需要3分钟就能做出一个视频,把视频发到B站.抖音.西瓜上,还能赚包辣条哦~ 文末给大家准备了AI变现的案例及AIGC知识库,记得领取哦! 1.收 ...

  2. 19c ADG Switchover 切换测试

    背景: 环境未配置DG Broker,手工切换ADG,19c也要比11g时代的切换更简单. 使用自己的测试环境,具体可参见: 单实例Primary快速搭建Standby RAC参考手册(19.16 A ...

  3. Nodepad++格式化XML和JSON字符串

    (一)格式化XML 1.安装XML Tools 在notepad++中点击菜单栏[插件]-[插件管理]. 在插件管理界面选择[XML Tools],点击[安装]. 2.打开XML文件 在notepad ...

  4. Nginx实战-公网LB限流配置等

    前提: Nginx要实现根据ip地址进行限流与不限流的区分需要通过源码包安装GeoIP模块 找到与yum安装版本相同的源码包,通过configure进行安装 ./configure --prefix= ...

  5. NC15077 造一造

    题目链接 题目 题目描述 WYF正试图用一个栈来构造一棵树,现在他已经构造了n个元素作为树的节点,只要将这n个元素依次入栈出栈就可以形成一棵树了.当然,这个问题与树并没有关系,所以它叫做WYF的栈.每 ...

  6. MVVM模式的理解

    MVVM模式的理解 MVVM全称Model-View-ViewModel是基于MVC和MVP体系结构模式的改进,MVVM就是MVC模式中的View的状态和行为抽象化,将视图UI和业务逻辑分开,更清楚地 ...

  7. jupyter环境变量配置与启动

    一.jupyter基础知识 1.基本概念 jupyter是基于网页的用于交互计算的应用程序.其可被应用于全过程计算:开发.文档编写.运行代码和展示结果. 编程时具有语法高亮,缩进,tab补全的功能. ...

  8. node版本管理工具nvm的安装及使用

    一.什么是nvm nvm是一个node版本管理工具. 由于不同项目依赖的node版本可能不同,所以在维护多个项目时通常需要使用不同的node版本,这时候用nvm来切换不同的node版本就很方便. 官方 ...

  9. Hi3516开发笔记(八):Hi3516虚拟机交叉开发环境搭建之配置QtCreator开发交叉编译环境

    海思开发专栏 上一篇:<Hi3516开发笔记(七):Hi3516虚拟机交叉开发环境搭建之交叉编译Qt>下一篇:<Hi3516开发笔记(九):在QtCreator开发环境中引入海思sd ...

  10. mysql中如何批量生成百万级数据

    # 准备 #1. 准备表 create table s1( id int, name varchar(20), gender char(6), email varchar(50), first_nam ...