Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >dotnet C# Windows 桌面应用程序简单使用 DwmFlush 对齐刷新率

dotnet C# Windows 桌面应用程序简单使用 DwmFlush 对齐刷新率

作者头像
林德熙
发布于 2025-06-17 01:24:19
发布于 2025-06-17 01:24:19
13800
代码可运行
举报
文章被收录于专栏:林德熙的博客林德熙的博客
运行总次数:0
代码可运行

在 Windows 桌面应用程序里面,可以简单地使用 DwmFlush 方法来与 DWM 对齐刷新率

桌面管理器 DWM (DWM Desktop Window Manager)是一个古老的机制,在 Windows 上的 DWM 将会收集每个窗口的绘制内容,然后将其进行合成,最后输出到屏幕上。通过 DWM 机制,可以避免应用程序直接将画面输出到屏幕上,允许多个应用程序之间叠加出绚丽的窗口化效果

调用 Dwmapi.dll 提供的 DwmFlush 方法,可以让调用方阻塞卡住,等待当前次渲染刷新完成之后才继续后续逻辑。通过这样的机制,就可以实现和 DwmFlush 对齐刷新率,其测试代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;

var stopwatch = new Stopwatch();

while (true)
{
    stopwatch.Restart();
    var hResult = DwmFlush();
    stopwatch.Stop();

    Console.WriteLine($"Elapsed={stopwatch.ElapsedMilliseconds}ms HResult={hResult}");

    if (hResult != 0)
    {
        // Fail
        break;
    }
}

Console.WriteLine("Hello, World!");

[DllImport("Dwmapi.dll")]
static extern int DwmFlush();

预期运行之后,将可以在控制台看到比较恒定的频率输出。在我的设备上是 60Hz 的刷新率,输出大概就是 16 毫秒。或偶尔跳几次 15 或 17 毫秒。但如果此时在循环里面多做一些事情,则可以看到其输出的毫秒数变短,但其控制台输出频率不变

由于 CPU/系统 的线程调度影响,平均的暂停时间预期会比单个 DwmFlush 略高。即在从 DwmFlush 方法释放出来之后,可能需要过一段时间才能获取 CPU 执行权,此时会导致时间略长

此方法也是 WPF 渲染刷新对齐的核心机制之一,如 WPF 框架的源代码所示:https://github.com/dotnet/wpf/blob/b6316f1cfeb486229ca61368df3bc203da482948/src/Microsoft.DotNet.Wpf/src/WpfGfx/core/uce/rendertargetmanager.cpp#L1171

本文代码放在 githubgitee 上,可以使用如下命令行拉取代码。我整个代码仓库比较庞大,使用以下命令行可以进行部分拉取,拉取速度比较快

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 9720d03f2dad4cc84682b784dd56c2b9fed8bb3f

以上使用的是国内的 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码。如果依然拉取不到代码,可以发邮件向我要代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 9720d03f2dad4cc84682b784dd56c2b9fed8bb3f

获取代码之后,进入 Workbench/DehemrallneFurwaiwakifije 文件夹,即可获取到源代码

更多技术博客,请参阅 博客导航

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
dotnet X11 窗口之间发送鼠标消息 模拟鼠标输入
本文记录我阅读 Avalonia 代码过程中所学习到的在 X11 的窗口之间发送鼠标消息,可以跨进程给其他进程的窗口发送鼠标消息,通过此方式可以实现模拟鼠标输入
林德熙
2024/05/16
1900
dotnet C# X11 开发笔记
如何类似 WPF 的 Owner 之类的关系?可使用 XSetTransientForHint 方法。比如有 a 和 b 两个窗口,使用下面代码即可设置 a 窗口一定在 b 窗口上方
林德熙
2024/04/03
2050
dotnet 设置 X11 建立窗口之间的父子关系
在 X11 里面有和 Win32 类似的窗口之间的关系机制,如 Owner-Owned 关系,以及 Parent-Child 关系。本文将告诉大家如何进行设置以及其行为
林德熙
2024/05/17
3200
dotnet 设置 X11 建立窗口之间的父子关系
OpenTK 入门 Vsync 垂直同步对刷新率的影响
在上一篇博客 OpenTK 入门 初始化窗口 告诉了大家如何初始化 OpenTK 承载 OpenGL 的窗口的应用,在上一篇博客基础上,咱尝试修改创建 MainWindow 的参数,从而测试 Vsync 垂直同步对刷新率的影响
林德熙
2023/04/09
5710
dotnet C# 警惕可空结构体的方法内部赋值无效
本文将记录一个 C# dotnet 里的一个稍微隐藏的行为,那就是如果有一个结构体存在某个的方法,此方法的作用是修改结构里面的字段或属性的值,那此时将会在可空的结构体调用此方法时,发现没有真正修改到可空结构体局部变量本身
林德熙
2024/03/18
2050
dotnet 后台线程发送 X11 窗口消息
核心是通过 XSendEvent 发送消息,发送消息想要有反应需要另开 XOpenDisplay 获取 display 对象,最后再将其关闭才能发送出去
林德熙
2024/05/16
2130
dotnet C# 调用委托的 GetInvocationList 的对象分配
本文也叫跟着 Stephen Toub 大佬学性能优化系列,这是我从 Stephen Toub 大佬给 WPF 框架做性能优化学到的知识,在热路径下,也就是频繁调用的模块,如果调用了委托的 GetInvocationList 方法,那么将视委托的大小,每次创建不同大小的新数组对象,而在频繁调用的模块,将会创建大量的对象
林德熙
2021/12/24
7190
dotnet C# 创建 X11 应用时设置窗口背景颜色
在 dotnet C# 设置 X11 应用窗口背景透明 的基础上,可以通过创建 XColor 结构体,将 XColor 赋值给到 XSetWindowAttributes 的 background_pixel 进行设置窗口的初始化背景颜色
林德熙
2024/06/01
1750
WPF 解决 SelectionTextBrush 设置无效问题
本文告诉大家在 WPF 里面设置 SelectionTextBrush 无效的问题,可以通过 AppContext 的开关开启其行为
林德熙
2024/04/03
2310
VisualStudio 调试时会不断刷新 WPF 应用渲染
在 VisualStudio 附加调试和没有用 VisualStudio 附加调试时,对应用程序是有不同的影响,如 VisualStudio 设计器将会在附加调试 WPF 应用的时候,不断刷新 WPF 应用的渲染。也就是说,如果你觉得界面视觉效果不对或者对,也许可以甩锅到 VisualStudio 上
林德熙
2021/12/23
6810
VisualStudio 调试时会不断刷新 WPF 应用渲染
WPF UNO 测试固定尺寸且水平和垂直对齐设置 Stretch 的元素在容器内的布局行为
本文将告诉大家我对 WPF 的自定义布局容器和自定义控件进行的布局行为测试中的一个小点,即测试固定元素的尺寸的情况下或元素尺寸为有限尺寸的情况下,同步设置元素的水平和垂直对齐为 Stretch 来测试元素在容器内的布局行为,元素分别在容器给元素的布局尺寸大于元素的尺寸和小于元素尺寸的行为
林德熙
2024/01/28
3970
WPF UNO 测试固定尺寸且水平和垂直对齐设置 Stretch 的元素在容器内的布局行为
dotnet 简单解压缩 tar gz 到文件夹
本文将和大家介绍如何在 dotnet 7 或更高版本里,使用不到 10 行可执行代码解压缩 tar.gz 压缩包到文件夹
林德熙
2025/07/03
90
WPF 获取 MediaContext 的方法
本文告诉大家如何通过反射获取 MediaContext 对象。在 WPF 里面,通过 MediaContext 对象可以用来控制渲染
林德熙
2022/08/12
3840
dotnet X11 设置窗口鼠标触摸命中穿透
本文记录如何在 X11 应用里面,使用 XShapeCombineRegion 方法配置一个 X11 窗口支持和 Win32 窗口一样的命中测试穿透功能,即对应 Win32 的 WS_EX_TRANSPARENT 的鼠标、触摸等的点击等动作的穿透功能,可以实现在窗口中挖空一块范围直接穿透到后面的窗口
林德熙
2024/05/22
3030
dotnet 在 UNO 里获取 X11 窗口指针的方法
在 UNO 的 5.2 版本,可以使用 X11 平台承载 UNO 应用。此时我需要获取到 UNO 应用的窗口的 X11 窗口指针,如此即可调用 X11 平台相关逻辑对 UNO 窗口执行一些交互
林德熙
2024/05/23
1410
dotnet C# 结构体出方法弹栈之后的行为
本文记录我在 .NET 9 里测试的行为,在方法里面创建的在栈上的结构体,在方法执行结束之后,栈上的结构体将会被弹栈进入不受管理区域,此时的结构体内存内容不会立刻被清空或被改写
林德熙
2024/08/24
1070
VisualStudio 如何 SSH 远程调试 Linux 的 dotnet 应用的启动
本文将告诉大家,如何使用 VisualStudio 2022 工具,通过 SSH 远程调试运行在 Linux 系统上的 dotnet 系应用的启动过程
林德熙
2024/06/08
6880
Avalonia 后台代码简单播放动画示例
本文将演示如何在 Avalonia 的后台代码里面创建 Animation 执行播放
林德熙
2024/08/20
2700
WPF 已知问题 监听 WMI 事件导致触摸失效
本文记录 WPF 的已知问题,在 .NET Core 版本的 WPF 应用里面,应用启动的过程监听 WMI 事件,将导致触摸模块 COM 接口获取失败,进而导致触摸失效
林德熙
2024/09/11
1550
dotnet C# 分享基础 for 循环的写法
使用 for 作为循环的写法是在编程里面常用的代码写法。比如说我有一个名为 Foo 的类型,这个类型提供了一个名为 GetCount 的方法,这个方法可以缓慢的获取 Foo 里面的一个代表数量的值。且在 Foo 类型里面提供了索引器,可以根据传入的下标序号返回一个字符串,例子代码如下
林德熙
2024/08/10
1650
推荐阅读
相关推荐
dotnet X11 窗口之间发送鼠标消息 模拟鼠标输入
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验