Как упоминалось ранее, «стандартный» способ WPF не даст вам требуемой производительности. Попробовав несколько разных бесплатных и коммерческих продуктов и не получив того, что мне нужно, я начал экспериментировать со следующими методами:
- Использование геометрии WPF.
- Использование Direct2D.
Оба они вообще не были исполнителями.
Одна вещь, которую я знаю, это то, что WPF хорош для рендеринга изображений (BitmapSource), поэтому я решил пойти в этом направлении и использовать WriteableBitmapEx, чтобы нарисовать график на WriteableBitmap и затем передать его ...
Одна проблема с библиотекой WriteableBitmapEx состоит в том, что она не имеет таких функций рисования, как, например, GDI. Так почему бы просто не использовать GDI? нет разницы, если вы все сделаете правильно.
Пример:
public void BeginDraw()
{
_writeable_bitmap = new WriteableBitmap((int)Math.Max(_size.Width, 1),
(int)Math.Max(_size.Height, 1), 96.0, 96.0, PixelFormats.Pbgra32, null);
_gdi_bitmap = new System.Drawing.Bitmap(_writeable_bitmap.PixelWidth,
_writeable_bitmap.PixelHeight,_writeable_bitmap.BackBufferStride,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb,
_writeable_bitmap.BackBuffer);
_writeable_bitmap.Lock();
_g = System.Drawing.Graphics.FromImage(_gdi_bitmap);
_g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
_g.Clear(System.Drawing.Color.Transparent);
}
public void DrawSeries(IEnumerable<System.Drawing.PointF> points)
{
_g.DrawCurve(dataSeries.GdiPen, points.ToArray());
}
public void EndDraw()
{
_writeable_bitmap.AddDirtyRect(new Int32Rect(0, 0,
_writeable_bitmap.PixelWidth, _writeable_bitmap.PixelHeight));
_writeable_bitmap.Unlock();
var cloned = _writeable_bitmap.Clone();
cloned.Freeze();
Dispatcher.BeginInvoke(new Action((() =>
{
Image = cloned;
})));
_g.Dispose();
}
Как вы можете видеть, я использую "специальный трюк" для рисования графики непосредственно в собственный растровый источник WPF с использованием GDI.
Я не уверен, что это правильный способ измерения, но с помощью этого метода мне удалось получить очень приличные результаты:
- Более 1 миллиарда точек данных.
- Частота обновления 5FPS.
- 10000 новых точек данных, выдвигаемых с частотой 100 Гц.
- 10% ЦП на ноутбуке i7 Core.
- Потоки пользовательского интерфейса и рендеринга WPF полностью свободны для других операций.
Я являюсь автором библиотеки с открытым исходным кодом RealTimeGraphX (для WPF и UWP), которая делает именно это.
https://github.com/royben/RealTimeGraphX
Остальные компоненты графика, за исключением фактического ряда линий, сделаны с использованием стандартных элементов управления и форм WPF, поэтому их можно легко настраивать и манипулировать.