0

我正在使用动态数据显示来绘制一些图。

它提供了一个名为 MarkerPointsGraph 的类来将标记呈现到屏幕上。OnRender 方法在 Render 期间被调用,这反过来又调用适当的标记(圆形、三角形等)的渲染方法。

    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 方法。

4

2 回答 2

1

您可以尝试冻结您的画笔:

if (marker != null)
{
    Brush b = new SolidColorBrush(data.MarkerColor);
    b.Freeze();  
    marker.Fill = b;  
    marker.Size = data.MarkerSize;  
}

Brushes.Red已经冻结,这可能就是您看到性能提升的原因。

于 2013-01-30T19:37:10.397 回答
1

在不了解您的设置的情况下,您的问题可能在于您正在创建SolidColorBrush一个相对紧凑的循环(而不是处理它们,但这是另一个问题)。该对象具有与创建新对象相关的大量开销,而 usingBrushes.Red使用相同的实例,因此没有相同的问题。如果您曾经创建自己的画笔,我认为您不会遇到同样的问题。

于 2013-01-30T19:39:44.953 回答