Here is the code sample:
ConcurrentCircularBuffer<byte[]> _cList = new ConcurrentCircularBuffer<byte[]>(10);
private Bitmap getBitmap()
{
byte[] bmpdata = _cList.Dequeue();
if (bmpdata != null && bmpdata.Length > 0)
{
GCHandle handle = GCHandle.Alloc(bmpdata, GCHandleType.Pinned);
try
{
Bitmap bmp = new Bitmap(1920, 1080, stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, handle.AddrOfPinnedObject());
return bmp;
}
catch (Exception ex)
{}
finally
{
handle.Free();
}
}
return null;
}
public string GetBase64Image()
{
Bitmap bmp = getBitmap();
if (bmp != null)
{
using (var ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png); // Here I got the System.AccessViolationException
byte[] buffer = ms.ToArray();
return Convert.ToBase64String(buffer);
}
}
}
In this case after few attempts of converting image to base64string I getting the AccessViolationException.
When I'm adding 'GC.Collect()' to my 'Finally' block, the exception doesn't appear. What am I doing wrong? Is there a way to avoid the using of GC.Collect()?
Source image - is the live-stream from IP-camera, that writes the byte array to implementation of ConcurrentQueue that stores last 10 images.
upd: exception thrown in the multi-thread with low latency between the executions.
upd2:
ConcurrentCircularBuffer<byte[]> _cList = new ConcurrentCircularBuffer<byte[]>(10);
public string GetBase64Image()
{
byte[] bmpdata = _cList.Dequeue();
if (bmpdata != null && bmpdata.Length > 0)
{
GCHandle handle = GCHandle.Alloc(bmpdata, GCHandleType.Pinned);
try
{
using (Bitmap bmp = new Bitmap(1920, 1080, stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, handle.AddrOfPinnedObject()))
{
using (var ms = new MemoryStream())
{
bmp.Save(ms, ImageFormat.Png);
return Convert.ToBase64String(ms.ToArray());
}
}
}
finally
{
handle.Free();
GC.Collect();
}
}
}
At this time is the best solution. Without GC.Collect() - accessviolation when saving bitmap to MemoryStream