嵌套Parallel.For循环内的同步

问题描述:

我想将常规for循环转换为Parallel.For循环。嵌套Parallel.For循环内的同步

这个 -

for (int i = 0; i < bitmapImage.Width; i++) 
{ 
    for (int x = 0; x < bitmapImage.Height; x++) 
    { 
     System.Drawing.Color oc = bitmapImage.GetPixel(i, x); 
     int gray = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11)); 
     System.Drawing.Color nc = System.Drawing.Color.FromArgb(oc.A, gray, gray, gray); 
     bitmapImage.SetPixel(i, x, nc); 
    } 
} 

进入这个 -

Parallel.For(0, bitmapImage.Width - 1, i => 
{ 
    Parallel.For(0, bitmapImage.Height - 1, x => 
    { 
     System.Drawing.Color oc = bitmapImage.GetPixel(i, x); 
     int gray = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11)); 
     System.Drawing.Color nc = System.Drawing.Color.FromArgb(oc.A, gray, gray, gray); 
     bitmapImage.SetPixel(i, x, nc); 
    }); 
}); 

它失败MESSAGE-

对象是目前在其他地方使用。

因为多线程试图访问非线程安全reasources。任何想法我如何能做到这一点?

System.Drawing.Color oc = bitmapImage.GetPixel(i, x); 
+0

您不能同时读取或修改资源。你的第一个版本是唯一可以工作的版本,添加锁定会增加开销并使其比第一个版本慢。 – Igor

+0

@Igor谢谢。我也是这么想的。 –

+0

由于图像是与GUI相关的类,因此用于单线程访问使用。您可以尝试在独立矩阵上进行计算,然后在单个for循环中更新图像。 – VMAtm

这不是一个干净的解决方案,看看你想达到什么目的。将一个镜头中的所有像素都取下来,然后在平行处理它们会更好。

我个人使用并大幅改善性能的替代方法是使用不安全的函数进行此转换以输出灰度图像。

public static byte[] MakeGrayScaleRev(byte[] source, ref Bitmap bmp,int Hei,int Wid) 
     {    
      int bytesPerPixel = 4; 

      byte[] bytesBig = new byte[Wid * Hei]; //create array to contain bitmap data with padding 

      unsafe 
      { 

       int ic = 0, oc = 0, x = 0; 
       //Convert the pixel to it's luminance using the formula: 
       // L = .299*R + .587*G + .114*B 
       //Note that ic is the input column and oc is the output column     
       for (int ind = 0, i = 0; ind < 4 * Hei * Wid; ind += 4, i++) 
       {       
        int g = (int) 
          ((source[ind]/255.0f) * 
          (0.301f * source[ind + 1] + 
          0.587f * source[ind + 2] + 
          0.114f * source[ind + 3])); 
        bytesBig[i] = (byte)g; 
       }  
      } 

      try 
      { 

       bmp = new Bitmap(Wid, Hei, PixelFormat.Format8bppIndexed); 

       bmp.Palette = GetGrayScalePalette(); 

       Rectangle dimension = new Rectangle(0, 0, Wid, Hei); 
       BitmapData picData = bmp.LockBits(dimension, ImageLockMode.ReadWrite, bmp.PixelFormat); 


       IntPtr pixelStartAddress = picData.Scan0; 

       Marshal.Copy(forpictures, 0, pixelStartAddress, forpictures.Length); 

       bmp.UnlockBits(picData); 

       return bytesBig; 

      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.StackTrace); 

       return null; 

      } 

     } 

它得到的输入图像的所有像素的字节组,它的高度和宽度以及输出所计算的灰度级阵列,和在REF BMP位输出灰度位图。

+1

+1谢谢。这可能对某人有所帮助,但由于某些其他原因,我可能不会使用此目录。 –

+0

如果您需要任何帮助,请告知我。此代码用于从RTSP摄像头获取流并将其转换为灰度,因此性能至关重要。 – farbiondriven