改进了在 C# GDI 中绘制的循环

本文关键字:绘制 循环 GDI | 更新日期: 2023-09-27 18:32:31

我得到了一个 for 循环,它必须运行 200,000 次调用图形。画线。这非常慢,我期待您帮助提高此循环的性能。当我尝试任务并行性时,它会给出错误"调用线程必须是 STA,因为许多 UI 组件都需要这个。我还尝试将循环一分为二并并行执行它们,这也会导致相同的错误。我已经删除了与该尝试相关的代码,并给出了必须针对性能进行优化的实际代码。

代码是

从数组列表中获取数据,数组列表是图形的数据点

    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.");
        }
    }

改进了在 C# GDI 中绘制的循环

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

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