开发者

C# Image: Attempted to read or write protected memory

I'm writing C# application which saves picture box screen to JPEG files.

One thread creating image:

IntPtr cop开发者_C百科yPtr = 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);
}

And other thread saves picture:

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

But sometimes i get this exception:

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)

I used lock call but it seems not very helpful. I can save image in same thread. But maybe there's any solution how to solve this problem while using threads. Thanks.


Check the declaration of your image variable. It is possible that you have it defined with public access. It is usually best to just define a private or local object within your code that you then lock e.g.

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

and then in your other thread code:

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


According to the documentation you should define a private object to use as a lock object. This line in particular:

In general, avoid locking on a public type, or instances beyond your code's control

ie:

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


Since you're creating a new image in the first thread each time, it won't be the same object that the second thread is locking on.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜