【问题标题】:Poor performance of concurrent Graphics.RotateTransform operations并发 Graphics.RotateTransform 操作的性能不佳
【发布时间】:2012-01-07 08:30:48
【问题描述】:

为什么跨多个线程运行并发 Graphics.RotateTransform 操作时速度没有显着提高?

这个例子展示了边际性能提升:

    static Bitmap rotate(Bitmap bitmap, float angle)
    {
        Bitmap rotated = new Bitmap(bitmap.Width, bitmap.Height);
        using (Graphics g = Graphics.FromImage(rotated))
        {
            g.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2);
            g.RotateTransform(angle);
            g.TranslateTransform(-(float)bitmap.Width / 2, -(float)bitmap.Height / 2);
            g.DrawImage(bitmap, new Point(0, 0));
        }
        return rotated;
    }

    static void Main(string[] args)
    {
        WebClient client = new WebClient();
        string fileName = Path.GetTempFileName();
        client.DownloadFile("http://i.imgur.com/Vwiul.png", fileName);
        Bitmap original = new Bitmap(fileName);

        DateTime start = DateTime.Now;
        rotateSingleThread(original);
        TimeSpan length = DateTime.Now - start;
        Console.WriteLine(string.Format("Single thread rotate took {0} ms", (int)length.TotalMilliseconds));

        start = DateTime.Now;
        rotateMultiThread(original);
        length = DateTime.Now - start;
        Console.WriteLine(string.Format("Multiple thread rotate took {0} ms", (int)length.TotalMilliseconds));

        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    static void rotateSingleThread(Bitmap original)
    {
        for (float a = 0; a < 360; a += 0.1F)
        {
            Bitmap rotated = rotate(original, a);
            rotated.Dispose();
        }
    }

    static void rotateMultiThread(Bitmap original)
    {
        int threadCount = Environment.ProcessorCount;
        int groupSize = 360 / threadCount;
        Thread[] threads = new Thread[threadCount];
        Bitmap[] bitmaps = new Bitmap[threadCount];
        for (int x = 0; x < threadCount; x++)
        {
            bitmaps[x] = new Bitmap(original);
            threads[x] = new Thread(delegate(object i)
            {
                int min = (int)i * groupSize; int max = min + groupSize;
                if ((int)i == threadCount - 1) max = 360;
                for (float a = min; a < max + 1; a+= 0.1F)
                {
                    Bitmap rotated = rotate(bitmaps[(int)i], a);
                    rotated.Dispose();
                }
            });
            threads[x].Start(x);
        }
        for (int x = 0; x < threadCount; x++) threads[x].Join();
    }

如何提高执行并发 Graphics.RotateTransform 操作的速度?

【问题讨论】:

    标签: c# .net system.drawing


    【解决方案1】:

    问题在于这些 GDI+ 调用阻塞每个进程(而不是每个线程),因此即使线程并行运行,对 graphics.... 的调用也会导致其他线程阻塞。这意味着它最终几乎是连续处理的。

    有关变通方法,请参阅以下问题中的各种答案,最上面的答案建议创建单独的进程。看起来您最终可能只是创建了一个辅助命令行实用程序或其他东西。您甚至可以花哨地连接标准输入和标准输出,这样您就可以将图像传递给旋转并在不进行 IO 操作的情况下取回新图像。

    Parallelizing GDI+ Image Resizing .net

    【讨论】:

    • 谢谢,我不知道GDI+会这样阻塞。
    【解决方案2】:

    我没有答案,但有一些想法可能会有所帮助:

    1. 您的线程是否在多个处理器上运行?
    2. 您如何衡量性能?请记住,UI 渲染始终是 单线程。

    【讨论】:

      猜你喜欢
      • 2018-08-01
      • 1970-01-01
      • 2021-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 2017-12-25
      相关资源
      最近更新 更多