改进C#GDI中的循环绘制

时间:2014-12-01 07:04:26

标签: c# winforms gdi

我有一个for循环,它必须运行200,000次调用graphics.DrawLine。这非常慢,我期待着您在提高此循环性能方面的帮助。当我尝试使用Task Parallellism时,它会给出错误"调用线程必须是STA,因为许多UI组件都需要这个。"我也试过将循环分成两个并且并行执行它们,这也会导致相同的错误。我删除了与该尝试相关的代码,并给出了必须针对性能进行优化的实际代码。

代码是

//从arraylist中获取数据,这是图表的数据点

    Graphics g = null;
    public Drawing(Graphics _g, DrawingData _Data)
    {
        g = _g;
        drawingData = _Data;           
    }
    private void FrameDrawLine1()
    {
        DataValueSet pds = null;
        DataValueSet ds = null;

        for (int i = 1; i < drawingData.data.Count; i++) // the count will be 100,000
        {               
            ds = (DataValueSet)drawingData.data[i];                           
            PlotColumne(pds, ds);
        }                    
    }

//获取有关图形参数的颜色和其他信息

    private void PlotColumne(DataValueSet pds, DataValueSet ds)
    {
        try
        {
            double totalSeconds = (drawingData.valueArea.maxDate - drawingData.valueArea.minDate).TotalSeconds;
            double xFrom = GetTimePixel(pds.time, totalSeconds);
            double xTo = GetTimePixel(ds.time, totalSeconds);
            PlotprintingDataset[] pt = initialisePlotprintingDataset();

            _referenceColumnindex++;
            PlotColumn column = null;
            for (int i = 0; i < drawingData.plotColumns.Count; i++) // this count will be around 50
            {
                column = (PlotColumn)drawingData.plotColumns[i];
                if (column.active)
                {
                    if (ValueIsNumber(Convert.ToDouble(ds.values[column.index]), Convert.ToDouble(pds.values[column.index])))
                    {
                        if (pt[column.index].X < -10000F)
                        {
                            pt[column.index].X = xFrom;
                            pt[column.index].Y = calculateYValueInGraph(column, Convert.ToDouble(pds.values[column.index]));
                        }

                        if (DrawLineInGraph(pds, ds,  column, pt))
                        {
                            pt[column.index].X = xTo;
                            pt[column.index].Y = calculateYValueInGraph(column, Convert.ToDouble(pds.values[column.index]));
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            GenericFunctions.ErrorMessage("Error has occured while plotting graph columns. Please try again.");
        }
    }

//检查点是否在图形区域中并调用绘制线方法

    private bool DrawLineInGraph(DataValueSet pds, DataValueSet ds, PlotColumn column, PlotprintingDataset[] pt)
    {
        double totalSeconds = (drawingData.valueArea.maxDate - drawingData.valueArea.minDate).TotalSeconds;
        double xTo = GetTimePixel(ds.time, totalSeconds);
        double value = Convert.ToDouble(ds.values[column.index]);
        double y2 = calculateYValueInGraph(column, Convert.ToDouble(ds.values[column.index]));
        double y1 = calculateYValueInGraph(column, Convert.ToDouble(pds.values[column.index]));

        if (IsPointInPlausibleArea(pt, column, pds, ds))
        {
               drawLine(column.color, pt[column.index].X, xTo, pt[column.index].Y, y2, column.interpolate, column.lineWidth);

            return true;
        }
        else
        {
            return false;
        }
    }

//在图表中绘制线条

    private void drawLine(Color color, double xFrom, double xTo, double yFrom, double yTo,
        bool interpolate, int lineWidth)
    {
        try
        {
            System.Windows.Shapes.Line newline = new System.Windows.Shapes.Line();
            Pen linePen = new Pen(new SolidBrush(color), lineWidth);
            float x1 = (float)xFrom;
            float x2 = (float)xTo;
            float y1 = (float)yFrom;
            float y2 = (float)yTo;

            if (interpolate)
            {
                g.DrawLine(linePen, x1, y1, x2, y2);
            }
            else
            {
                g.DrawLine(linePen, x1, y1, x2, y1);
                g.DrawLine(linePen, x2, y1, x2, y2);
            }
        }
        catch (Exception ex)
        {
            GenericFunctions.ErrorMessage("Error has occured while drawing graph lines. Please try again.");
        }
    }

1 个答案:

答案 0 :(得分:0)

您应该尝试绘制图像。要执行此操作,您需要从位图创建自己的图形上下文。

Bitmap yourBitmap = new Bitmap(your controls width, height, PixelFormat. Format32bppArgb)
GRAPHICS G = Graphics.FromImage(yourBitmap)
// Draw your lines here

最后,您必须使用原始图形上下文将图片绘制到控件中。     e.Graphics.DrawImageUnscaled(0,0,yourBitmap)

此外,您可以调整图形上下文的参数。它们对性能也有很大的影响。

这是指向这些参数的链接:https://stackoverflow.com/a/38262796/6439999