C# System.AccessviolationException and using GC.Collect

Viewed 114

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

0 Answers
Related