Производительность графиков WPF в реальном времени с использованием PathGeometry - PullRequest
1 голос
/ 12 марта 2011

Я пытаюсь реализовать диаграмму, которая может обрабатывать данные в реальном времени, которые поступают каждые 1 мс.Я опрашиваю 50 мс данных, чтобы не пытаться перерисовывать экран каждую мс.Я использую PathGeometry на холсте, чтобы добавить отрезки.Я всегда вижу, как частота кадров постоянно снижается, так как перерисовки растут все медленнее и медленнее.Я не думал, что для моего компьютера будет так сложно отрисовать линию с примерно 10 000 точек.Я что-то не так делаю?Или есть какая-то другая философия дизайна, которая может быть более искусной в обработке данных в реальном времени в WPF?

В ViewModel у меня есть:

public PointCollection LinePoints;

В представлении, которое я слушаю, эта коллекция являетсяизменили и добавили отрезки:

_viewModel.LinePoints.Changed += LinePoints_Changed;

void LinePoints_Changed(object sender, System.EventArgs e)
{
    while (_viewModel.LinePoints.Count - 1 > pathFigure.Segments.Count)
    {
        // pathFigure is part of the PathGeometry on my canvas
        pathFigure.Segments.Add(new LineSegment(_viewModel.LinePoints[pathFigure.Segments.Count], true));
    }
}

Для целей моделирования я добавляю точки, используя BackgroundWorker:

void addPointsWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker bw = sender as BackgroundWorker;
    DateTime startTime = DateTime.Now;

    int numPointsAdded = 0;

    while (!bw.CancellationPending && (DateTime.Now - startTime).Seconds < 10)
    {
        List<Point> points = new List<Point>();

        for (int i = 0; i < 50; i++)
        {
            Math.Sin(numPointsAdded++/(500*Math.PI))));
        }

        System.Threading.Thread.Sleep(50);

        bw.ReportProgress(0, points);
    }
}

public void addPointsWorker_ProgressChanged(List<Point> pointsToAdd)
{
    foreach(Point point in pointsToAdd)
    {
        // triggers CollectionChanged which will add the line segments
        ViewModel.LinePoints.Add(point);
    }
}

Наряду с замедлением я также испытываю неотзывчивость пользовательского интерфейса.Я полагал, что это потому, что я делаю слишком много вызовов ReportProgress и заполняю насос сообщений, но если бы я смог решить медленный рендеринг, я думаю, что эта другая проблема также исчезла бы.Я открыт для любых предложений!

Ответы [ 2 ]

2 голосов
/ 12 марта 2011

У меня есть два предложения:

  1. Убедитесь, что ваша коллекция содержит только точки, которые будут отображаться на экране. Простой способ сделать это - использовать очередь и убрать ее с фронта по мере добавления дополнительных точек. Я сомневаюсь, что все 10000 очков должны быть оказаны одновременно.
  2. Если это все еще не дает вам требуемой производительности, вы можете использовать механизм рисования более низкого уровня. StreamGeometry будет первой попыткой. После этого WriteableBitmap обеспечит наилучшую возможную производительность в WPF.
0 голосов
/ 18 марта 2011

Через некоторое время я обнаружил, что Чарли - лучшее решение.Я также обнаружил, что вместо использования LineSegment каждый раз, когда добавляется точка, использование PolyLineSegment с примерно 50-ю точками данных, которые я уже поставил в очередь, творит чудеса с производительностью.

Однако, это не задерживает неизбежное замедление, которое происходит.Но использование комбинации PolyLineSegment только с последними несколькими сотнями или даже тысячами точек дало мне наилучшую производительность при отображении максимально возможного количества данных.

...