加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何检测何时重绘WPF控件?

发布时间:2020-12-15 21:50:44 所属栏目:百科 来源:网络整理
导读:我正在使用D3D Image显示一系列帧,这些帧一个接一个地呈现在同一个Direct3D Surface中.我现在的逻辑是这样的: 显示最后渲染的帧(ieD3DImage.Lock()/ AddDirtyRect()/ Unlock()) 开始渲染下一帧 等待下一帧准备就绪,是时候显示它了 显示上次渲染的帧 …… 这
我正在使用D3D Image显示一系列帧,这些帧一个接一个地呈现在同一个Direct3D Surface中.我现在的逻辑是这样的:

>显示最后渲染的帧(ieD3DImage.Lock()/ AddDirtyRect()/ Unlock())
>开始渲染下一帧
>等待下一帧准备就绪,是时候显示它了
>显示上次渲染的帧
> ……

这种方法的问题在于,当我们在D3DImage上调用Unlock()时,图像实际上没有被复制,它只被安排在下一个WPF渲染上复制.因此,在WPF有机会显示之前,我们可能会在Direct3D表面上渲染一个新帧.最终结果是我们在显示器上看到错过的帧.

现在我正在尝试使用单独的Direct3D纹理进行渲染,并在显示之前执行复制到“显示纹理”,这样可以提供更好的结果,但会产生大量的开销.最好能够知道D3DImage何时完成刷新并立即开始渲染下一帧.这有可能,如果是这样的话怎么样?或者你有一个更好的想法?

谢谢.

解决方法

当WPF要渲染时调用 CompositionTarget.Rendering event,所以当你应该执行Lock()和Unlock()时.解锁()后,您可以启动下一个渲染.

您还应该检查RenderingTime,因为事件可能每帧触发多次.尝试这样的事情:

private void HandleWpfCompositionTargetRendering(object sender,EventArgs e)
{
    RenderingEventArgs rea = e as RenderingEventArgs;

    // It's possible for Rendering to call back twice in the same frame
    // so only render when we haven't already rendered in this frame.
    if (this.lastRenderTime == rea.RenderingTime)
        return;

    if (this.renderIsFinished)
    {
        // Lock();
        // SetBackBuffer(...);
        // AddDirtyRect(...);
        // Unlock();

        this.renderIsFinished = false;
        // Fire event to start new render
        // the event needs to set this.renderIsFinished = true when the render is done

        // Remember last render time
        this.lastRenderTime = rea.RenderingTime;
    }
}

更新以解决评论

你确定有竞争条件吗? This page表示在调用Unlock()时会复制后台缓冲区.

如果确实存在竞争条件,那么在渲染代码周围放置锁定/解锁怎么样? This page表示Lock()将阻止,直到副本完成.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读