我正在使用动态数据显示绘制一些图。
它提供了一个名为MarkerPointsGraph的类,用于将标记渲染到屏幕上。在渲染期间调用OnRender方法,然后调用相应的标记(圆形,三角形等)渲染方法。
protected override void OnRenderCore(DrawingContext dc, RenderState state)
{
if (DataSource == null) return;
if (Marker == null) return;
var transform = Plotter2D.Viewport.Transform;
DataRect bounds = DataRect.Empty;
using (IPointEnumerator enumerator = DataSource.GetEnumerator(GetContext()))
{
Point point = new Point();
while (enumerator.MoveNext())
{
enumerator.GetCurrent(ref point);
enumerator.ApplyMappings(Marker);
//Point screenPoint = point.Transform(state.Visible, state.Output);
Point screenPoint = point.DataToScreen(transform);
bounds = DataRect.Union(bounds, point);
Marker.Render(dc, screenPoint);
}
}
Viewport2D.SetContentBounds(this, bounds);
}
/// <summary>Renders circle around each point of graph</summary>
public class CirclePointMarker : ShapePointMarker {
public override void Render(DrawingContext dc, Point screenPoint) {
dc.DrawEllipse(Fill, Pen, screenPoint, Size / 2, Size / 2);
}
}
现在,我的主叫代码如下所示。
plotter.AddLineGraph(
data.Data,
new Pen
{
Brush = Brushes.Violet,
DashStyle = DashStyles.DashDot,
Thickness = 3
},
GetMarker(data),
new StandardDescription(data.Title));
我在性能方面注意到的主要区别在于以下方法。
参考ChartData类的数据
private ShapePointMarker GetMarker(ChartData data)
{
ShapePointMarker marker = null;
switch (data.MarkerShape)
{
case Shapes.Circle:
marker = new CirclePointMarker();
break;
case Shapes.Triangle:
marker = new TrianglePointMarker();
break;
case Shapes.None:
default:
marker = null;
break;
}
if (marker != null)
{
//Referring to stuff here.
marker.Fill = new SolidColorBrush(data.MarkerColor);
marker.Size = data.MarkerSize;
}
return marker;
}
硬编码数据代替参考。
private ShapePointMarker GetMarker(ChartData data)
{
ShapePointMarker marker = null;
switch (data.MarkerShape)
{
case Shapes.Circle:
marker = new CirclePointMarker();
break;
case Shapes.Triangle:
marker = new TrianglePointMarker();
break;
case Shapes.None:
default:
marker = null;
break;
}
if (marker != null)
{
//Hard coding stuff here.
marker.Fill = Brushes.Red;
marker.Size = 5;
}
return marker;
}
仅仅通过将GetMarker方法中的基于参考的数据更改为硬编码值,我看到渲染时间提高了近100倍。
C#的哪些行为会导致这种差异?
编辑:MarkerPointsGraph不为每个点创建Marker对象。它只调用render方法。
答案 0 :(得分:1)
您可以尝试冻结画笔:
if (marker != null)
{
Brush b = new SolidColorBrush(data.MarkerColor);
b.Freeze();
marker.Fill = b;
marker.Size = data.MarkerSize;
}
Brushes.Red
已经冻结,这可能是您看到效果提升的原因。
答案 1 :(得分:1)
在不了解您的设置的情况下,您的问题可能在于您在相对紧凑的循环中创建SolidColorBrush
(并且不处理它们,但这是另一个问题)。该对象具有与创建新对象相关的相当大的开销,而使用Brushes.Red
使用相同的实例,因此没有相同的问题。如果你想创造自己的画笔,我认为你不会看到同样的问题。