C#Image:尝试读取或写入受保护的内存

时间:2010-08-17 08:10:08

标签: c# multithreading image

我正在编写C#应用程序,它将图片框屏幕保存为JPEG文件。

创建图像的一个线程:

IntPtr copyPtr = new IntPtr((void*)pArray);
image = new Bitmap(bitmapInfo.biWidth, Math.Abs(bitmapInfo.biHeight), bitmapInfo.biWidth * 3, PixelFormat.Format24bppRgb, copyPtr);
lock (image)
{
   this.CreateGraphics().DrawImage(image, (window_width - (width * new_value)) / 2, (window_height - (height * new_value)) / 2, width * new_value, height * new_value);
}

其他帖子保存图片:

try
{
       while ((t < (time * 60 * 1000)) && !done)
       {
          lock (image)
          {
          image.Save(folder + this.filename + DateTime.Now.ToString("yyyMMddHHmmssFFFFFFF") + ".jpg", ImageFormat.Jpeg);
          }
          t = t + interval;
          System.Threading.Thread.Sleep(interval);
          i++;
       }
}
catch (Exception e)
{
  Console.WriteLine("Exception: " + e.Message);
  Console.WriteLine("Stack trace: " + e.StackTrace);
} 

但有时我得到这个例外:

Exception: Attempted to read or write protected memory. This is often an indicat
ion that other memory is corrupt.
Stack trace:    at System.Drawing.SafeNativeMethods.Gdip.GdipSaveImageToFile(Han
dleRef image, String filename, Guid& classId, HandleRef encoderParams)
   at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, Encoder
Parameters encoderParams)
   at System.Drawing.Image.Save(String filename, ImageFormat format)
   at MyDLL.Window.SaveJPEG(String filename, Int32 fps, Int32
 time)

我使用了锁定电话,但似乎没有用。我可以在同一个线程中保存图像。但也许有任何解决方案如何在使用线程时解决这个问题。感谢。

3 个答案:

答案 0 :(得分:2)

检查image变量的声明。 您可以使用公共访问权限定义它。 通常最好只在代码中定义一个私有或本地对象,然后锁定,例如。

Object imageLock = new Object();
IntPtr copyPtr = new IntPtr((void*)pArray);
image = new Bitmap(bitmapInfo.biWidth, Math.Abs(bitmapInfo.biHeight), bitmapInfo.biWidth * 3, PixelFormat.Format24bppRgb, copyPtr);
lock (imageLock)
{
   this.CreateGraphics().DrawImage(image, (window_width - (width * new_value)) / 2, (window_height - (height * new_value)) / 2, width * new_value, height * new_value);
}

然后在你的其他线程代码中:

Object imageLock = new Object();
try
{
       while ((t < (time * 60 * 1000)) && !done)
       {
          lock (imageLock)
          {
          image.Save(folder + this.filename + DateTime.Now.ToString("yyyMMddHHmmssFFFFFFF") + ".jpg", ImageFormat.Jpeg);
          }
          t = t + interval;
          System.Threading.Thread.Sleep(interval);
          i++;
       }
}
catch (Exception e)
{
  Console.WriteLine("Exception: " + e.Message);
  Console.WriteLine("Stack trace: " + e.StackTrace);
} 

答案 1 :(得分:1)

根据documentation,您应该定义一个私有对象以用作锁定对象。特别是这一行:

一般情况下,避免锁定公共类型或超出代码控制范围的实例

即:

object lockObject = new object();
IntPtr copyPtr = new IntPtr((void*)pArray); 
image = new Bitmap(bitmapInfo.biWidth, Math.Abs(bitmapInfo.biHeight), bitmapInfo.biWidth * 3,  PixelFormat.Format24bppRgb, copyPtr); 
lock (lockObject) 
{ 
   this.CreateGraphics().DrawImage(image, (window_width - (width * new_value)) / 2, (window_height - (height * new_value)) / 2, width * new_value, height * new_value); 
} 

答案 2 :(得分:0)

由于您每次都在第一个线程中创建一个新图像,因此它不会与第二个线程锁定的对象相同。