Плавная анимация WPF с удаленного рабочего стола на виртуальную машину - PullRequest
0 голосов
/ 09 июля 2020

Итак, я пытаюсь сделать стыковочную библиотеку очень похожей на те, которые используются в 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 по-прежнему довольно приличная. Есть ли способ улучшить эту работу? Спасибо.

EDIT: есть ли способ сделать плавную анимацию для Winforms?

EDIT 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 имеет аппаратное ускорение на совместимых машинах, но я не вижу использования графического процессора на моей dev-машине) Что касается ответа на этот вопрос, как мне сделать это быстрее?

1 Ответ

0 голосов
/ 09 июля 2020

Эти проблемы типичны для WPF и вызваны удаленным взаимодействием растровых изображений, см. Этот блог Microsoft .

Начиная с версии NET 3.5 SP1 (включая NET 4), WPF отображает содержимое приложения с помощью программного растеризатора на сервере, а затем удаляет содержимое в виде растровых изображений во всех случаях.

Это очень важно для анимации из-за большого количества перерисовок. Анимация часто затрагивает сразу большую площадь, представьте себе цветовой градиент. Следовательно, необходимо сделать недействительными и перерисовать большие части приложения. Кроме того, отсутствует поддержка окклюзии в WPF, что тоже может усугубить проблему.

Растровые изображения сильно сжимаются базовым стеком RD C, и обновляются только те области, которые были изменены . Также обратите внимание, что WPF в настоящее время не имеет эффективной поддержки окклюзии, поэтому, например, анимация, которая полностью скрыта за другими непрозрачными элементами WPF, по-прежнему будет вызывать недействительность и обновление RDP.

Причина, по которой вы можете не воспользоваться этим Проблема для eaxmple в собственных приложениях Win32 или MF C заключается в том, что они используют GDI или GDI + для рисования элементов управления пользовательского интерфейса.

Когда приложения используют GDI (например, многие приложения Win32 и Winforms), удаляются только примитивы GDI. Во многих случаях это может быть более эффективным, чем удаленное взаимодействие с приложениями WPF, поскольку приложения WPF удаляют растровые изображения, что обычно приводит к отправке большего количества контента по сети, чем аналогичное приложение на основе GDI. Дополнительные данные могут привести к снижению производительности в зависимости от пропускной способности сети, размера и частоты обновлений.

Atom и VS Code построены на Electron, который основан на хроме, а не на WPF, поэтому большие различия на удаленном рабочем столе.

В связанном блоге вы можете найти советы о том, как улучшить удаленную производительность в целом. Помимо рассмотрения возможности отключения анимации в сценарии удаленного рабочего стола ios, поскольку нет никаких гарантий по таким факторам, как пропускная способность или задержка для ваших клиентов, важными частями для улучшения анимации являются:

  • Адаптируйте DesiredFrameRate для уменьшения частоты кадров анимации, что, в свою очередь, снижает трафик c
  • Отключите анимацию в закрытых областях приложения, так как они также вызывают перерисовку
  • Уменьшить трафик c путем удаления анимации из стандартных шаблонов элементов управления WPF для ProgressBar, Button, ComboBox и других, а также всех ваших собственных несущественных анимаций
  • Повышение эффективности сжатия RDP за счет упрощения других областей приложения, например, замена цветовых градиентов на solid цвета
  • Избегайте всего, что медленно обрабатывается в программном обеспечении, например растровых эффектов или 3D-представлений
  • Используйте инструмент профилирования производительности WPF, например Perforator для выявления критических областей, которые часто становятся недействительными, для их оптимизации * 10 42 *
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...