【问题标题】:Smooth WPF animations on Remote Desktop to VM将远程桌面上的 WPF 动画平滑到 VM
【发布时间】:2020-10-29 17:25:38
【问题描述】:

所以我正在尝试制作一个与 VSCode 和 Atom 中使用的非常相似的对接库,但是我遇到了一些问题。基本上,首先,我需要制作一个从宽度 0 开始的框,以增加到屏幕的末尾。我能够做到这一点:

Rectangle rectangle = new Rectangle();
myCanvas.Children.Add(rectangle);
rectangle.Width = 0;
rectangle.Height = ActualHeight;
rectangle.Fill = new SolidColorBrush(Color.FromArgb(80, 120, 120, 120));
Storyboard sb = new Storyboard();
DoubleAnimation da = new DoubleAnimation(rectangle.Width, ActualWidth, new Duration(TimeSpan.FromMilliseconds(1000)));

Storyboard.SetTargetProperty(da, new PropertyPath("(Rectangle.Width)"));
sb.Children.Add(da);

rectangle.BeginStoryboard(sb);

动画在我的开发机器上非常流畅,但是当远程桌面进入虚拟机时,动画非常不稳定。但是,VSCodes 和 Atoms 动画仍然相当不错。有什么办法可以使这项工作更好吗? 谢谢。

编辑: 有没有办法为 Winforms 制作流畅的动画?

编辑 2: 所以我在这里有这个 Winforms GDI 代码示例:

private void FastTimer_Tick(object sender, EventArgs e)
{
    var x = 1;
    if (solidBrush == IntPtr.Zero)
    {
        solidBrush = CreateSolidBrush(ColorTranslator.ToWin32(Color.FromArgb(120, 120, 120)));
        hDC = CreateGraphics().GetHdc();
    }

    index += x;

    int w = x;
    int h = Height;

    //create memory device context
    var memdc = CreateCompatibleDC(hDC);

    //create bitmap
    var hbitmap = CreateCompatibleBitmap(hDC, index, h);

    ////select bitmap in to memory device context
    var holdbmp = SelectObject(memdc, hbitmap);


    RECT rect = new RECT(new Rectangle(0, 0, w, h));
    FillRect(memdc, ref rect, solidBrush);
    
    AlphaBlend(hDC, index - x, 0, w, h, memdc, 0, 0, w, h, new BLENDFUNCTION(0, 0, 128, 0));
    SelectObject(memdc, holdbmp);
    DeleteObject(hbitmap);
    DeleteDC(memdc);
}

快速定时器核心是这样的(测试中间隔为1000):

double frequency = Stopwatch.Frequency;
long prevTicks = 0;
while (true)
{
    if (!_enabled)
    {
        return;
    }
    double interval = frequency / Interval;
    long ticks = Stopwatch.GetTimestamp();
    if (ticks >= prevTicks + interval)
    {
        prevTicks = ticks;
        Tick?.Invoke(this, EventArgs.Empty);
    }
}

但是,远程桌面上的动画仍然不稳定。 (我知道 RD 不能使用硬件加速,但我认为 GDI 在兼容机器上是硬件加速的,但我在我的开发机器上没有看到任何 GPU 使用情况) 关于 thatguys 的回答,我怎样才能让它更快?

【问题讨论】:

  • 您的问题是您正在创建的重新绘制的数量以及从远程机器通过电线发送到查看器的事实。使用基于 css 的动画,它们在浏览器中本地运行。使用 wpf 它会为您的矩形设置一个像素的动画,这会使矩形无效,因此它会被重新绘制,它会被发送到您的查看机。它为另一个像素设置动画,同样的情况也会发生。然后一次又一次。多次。从本质上讲,您几乎构建了一个动画,该动画可能旨在通过远程连接影响观看体验。

标签: c# .net wpf winforms animation


【解决方案1】:

这些问题在 WPF 中很常见,并且是由位图远程处理引起的,请参阅此Microsoft blog

从 NET 3.5 SP1(包括 NET 4)的发布开始,WPF 使用服务器上的软件光栅器呈现应用程序内容,然后在所有情况下将内容作为位图远程处理。

这对于动画来说至关重要,因为需要大量重绘。动画通常会同时影响大面积,想象一下颜色渐变。因此,应用程序的很大一部分需要作废并重新绘制。此外,WPF 中缺乏对遮挡的支持,这也可能使问题更加严重。

位图被底层 RDC 堆栈高度压缩,并且只有更改的区域才会被更新。另请注意,WPF 目前没有有效的遮挡支持,因此例如完全隐藏在其他不透明 WPF 元素后面的动画仍将强制失效和 RDP 更新。

您可能不会在本机 Win32 或 MFC 应用程序中遇到此问题的原因是它们使用 GDI 或 GDI+ 来绘制其用户界面控件。

当应用程序使用 GDI(例如许多 Win32 和 Winforms 应用程序)时,只有 GDI 原语被远程处理。在许多情况下,这可能比远程处理 WPF 应用程序更有效,因为 WPF 应用程序远程处理位图,这通常会导致比类似的基于 GDI 的应用程序通过网络发送更多的内容。额外的数据可能会导致性能下降,具体取决于网络带宽以及更新的大小和频率。

Atom 和 VS Code 是基于 Electron 构建的,它基于 Chromium,而不是 WPF,这就是远程桌面存在很大差异的原因。

在链接的博客中,您可以找到有关如何总体提高远程性能的提示。除了考虑在远程桌面场景中禁用动画(因为无法保证客户端的带宽或延迟等因素)之外,改进动画的基本部分是:

  • 调整DesiredFrameRate 以降低动画帧率,从而减少流量
  • 关闭应用程序被遮挡区域的动画,因为它们也会导致重绘
  • 通过从ProgressBarButtonComboBox 和其他人的默认 WPF 控件模板中删除动画以及您自己的所有非必要动画来减少流量
  • 通过简化应用程序的其他领域(例如用纯色替换颜色渐变)来提高 RDP 压缩效率
  • 避免在位图效果或 3D 视图等软件中呈现缓慢的任何内容
  • 使用像 Perforator 这样的 WPF 性能分析工具来识别经常失效的关键区域以优化它们

【讨论】:

  • 这如何回答这个问题?
  • @Andy 我添加了一些关于如何提高动画性能的提示。其余的解释了远程处理通常会对使用 WPF 时的响应能力造成严重影响,以及它的原因。我从这个问题中得出结论,VS-ux 可能正在处理非常昂贵的动画。因此,我只是说明存在改进的选项,但由于动画通常会阻碍 WPF 远程处理性能,因此在这种情况下考虑不使用动画可能会更好,因为带宽等许多因素都无法保证。
  • @thatguy 您好,感谢您的回答。我想知道您是否可以查看我对问题所做的修改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多