You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core中能否访问图形硬件屏幕刷新事件?

WinForms绘图与屏幕刷新率同步方案
  • WinForms本身没有提供直接的屏幕刷新事件,但可以通过Windows API或DirectX实现与屏幕刷新率(60/72/144Hz等)的精准同步,替代精度不足的普通计时器。
  • 普通System.Windows.Forms.Timer依赖系统消息循环,精度仅能达到15ms左右,无法匹配高刷新率的帧间隔(比如60Hz对应16.666ms),必须换用高精度方案:

方案一:Windows高性能计时器(QueryPerformanceCounter)

  • 先通过QueryDisplayConfig获取当前屏幕的刷新率,计算单帧间隔时间(单位为性能计数器的计数)。
  • 用QueryPerformanceCounter跟踪时间差,当累计时间达到帧间隔时触发重绘,重置计时起点。这种方式能做到亚毫秒级精度,完全覆盖各类刷新率需求。
  • 核心代码示例:
    using System.Runtime.InteropServices;
    
    private long _lastFrameTime;
    private long _performanceFrequency;
    private double _frameIntervalTicks;
    
    // 初始化高性能计时器相关API
    [DllImport("kernel32.dll")]
    static extern bool QueryPerformanceFrequency(out long lpFrequency);
    [DllImport("kernel32.dll")]
    static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
    
    void InitializeFrameSync()
    {
        QueryPerformanceFrequency(out _performanceFrequency);
        int refreshRate = GetCurrentScreenRefreshRate(); // 自行实现获取当前屏幕刷新率的API逻辑
        _frameIntervalTicks = (double)_performanceFrequency / refreshRate;
        QueryPerformanceCounter(out _lastFrameTime);
    }
    
    // 在后台线程中执行帧同步检测
    void CheckFrameSync()
    {
        long currentTime;
        QueryPerformanceCounter(out currentTime);
        if (currentTime - _lastFrameTime >= _frameIntervalTicks)
        {
            this.Invoke((Action)(() => this.Invalidate()));
            _lastFrameTime = currentTime;
        }
    }
    

方案二:DirectX垂直同步绑定

  • 如果绘图逻辑可以结合DirectX(比如使用SharpDX封装库),开启垂直同步(VSync)后,DirectX会在屏幕每次刷新时自动触发渲染回调,完全匹配硬件刷新率,无计时偏差。

  • 这种方式是精度最高的方案,直接与显卡的垂直同步信号绑定,适合对帧同步要求极高的场景。

  • 注意事项:

    • 高精度计时器逻辑要放在后台线程执行,避免阻塞UI线程;通过Control.Invoke触发UI重绘。
    • 需处理系统睡眠、分辨率变更等场景,及时重新获取刷新率并调整帧间隔。

内容的提问来源于stack exchange,提问作者J Collins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:59:54