0

我正在改进我创建的 3d 引擎的性能,引入 LockBits 和并行处理。我有一个引擎类,它使用以下方法更新位图的结果:

 public void draw() {

        clearbmp();

        // locking bmp
        BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, W, H), ImageLockMode.ReadWrite, bmp.PixelFormat);
        IntPtr FirstPixel = bitmapData.Scan0;
        int bytes = Math.Abs(bitmapData.Stride) * H;
        bpp = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8;
        rgbarray = new byte[bytes];
        System.Runtime.InteropServices.Marshal.Copy(FirstPixel, rgbarray, 0, bytes);

        int count = 0;
        for (int k = 0; k < solidos.Count; k++)
        {
            if (solidos[k] != null && solidos[k].draw)
            {
                // separating faces of the solid into different threads
                Parallel.ForEach(solidos[k].side, f =>
                {
                    // ... do the operations...
                });
            }
        }

        // copy the array to the bitmap and unlock
        System.Runtime.InteropServices.Marshal.Copy(rgbarray, 0, FirstPixel, bytes);
        bmp.UnlockBits(bitmapData);

代码按预期运行以生成图像,但当主程序要求它快速连续更新多次时失败,错误发生在bmp.UnlockBits(bitmapData)中,异常为“GDI+ 中的通用错误”

根据我从研究中收集到的信息,我想这是因为该方法在完成第一次之前第二次运行,因此试图解锁已经解锁的数据。

如果这是正确的,那么在创建新线程时如何中止正在运行的线程?最后一个电话永远是最重要的

4

1 回答 1

0
  1. 在开始新呼叫之前,请等待现有呼叫完成。你可以通过简单地使用一个lock区域来做到这一点。这解决了正确性问题。Task也许让每个计算都运行在using中会更容易Task.Run。结果Task对象是该计算的句柄,可用于等待它完成。
  2. 如果您想加快完成不再需要的旧计算运行,请添加取消机制。在这里,您可以使用volatile bool cancel = false;. 设置true为取消。在您的并行循环中(可能还有其他地方),定期检查该布尔变量,如果找到则终止true。您也可以使用CancellationTokenSource.
于 2018-01-10T22:27:45.853 回答