tags:

views:

179

answers:

3

It look desceptively easy to use System.Drawing to create thumbnails in your ASP.NET application. But MSDN tells you:

Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions.

I'm seeing intermittented 'out of memory' errors within this type of GDI+ code. I'm beginning to suspect this is the cause.

How ARE people doing server side image manipulation? Can anyone recommend any alternative that WON'T blow up my server?

The relevant code below. The exception intermittently happens in System.Drawing.Graphics.DrawImage. I've just inherited this project, so I'd need to check the logs to see how often this is being hit / how often we get an exception...

public byte[] Resize(int newWidth, int newHeight, Image orignalImage)
{
    Bitmap bitmap = new Bitmap(newWidth, newHeight);
    Graphics g = Graphics.FromImage(bitmap);
    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

    Rectangle r = new Rectangle(0, 0, newWidth, newHeight);
    g.DrawImage(orignalImage, r, r.X, r.Y, orignalImage.Width, orignalImage.Height, GraphicsUnit.Pixel);

    MemoryStream stream = new MemoryStream();
    bitmap.Save(stream, ImageFormat.Jpeg);

    // clean up memory leaks
    if (bitmap != null)
    {
        bitmap.Dispose();
        bitmap = null;
    }
    if (g != null)
    {
        g.Dispose();
        g = null;
    }


    return stream.ToArray();
}

UPDATE: I've searched thru the whole project for anywhere we are using GDI+ and put using() { } around everything that's IDisposable. I haven't seen one 'out of memory' exception since I did this.

A: 

Why don't you set up a separate work server that is exposed through a web service.

ChaosPandion
Microsoft seem to suggest System.Drawing in any ASP.NET service is a no-no...
TesterTurnedDeveloper
+2  A: 

Assuming you will be doing "stuff" per request, the issues might be

  1. Processor intensive operation: manipulation of images, which could take time.

  2. In case you are saving the file, it will lead to disk issues.

  3. You can consider using HTTP handlers,

  4. Disposing System.Drawing objects should be a priority(using(){} statement )

  5. Asynchronous Pages can be explored here.

PRR
I did a custom IHTTPHandler for image resizing, worked a charm. Never had any problems with it ... but I wouldn't say it was very heavily stressed.
Rabid
+1 for Using - at the very least that lot should be wrapped up inside try{} catch{} finally{}
iAn
Accepted for point no. 4. I don't think HTTP handlers, or Asynchronous Pages are relevant here. Putting using around everything has appeared to stop the exceptions I was seeing.
TesterTurnedDeveloper
A: 

I would recommend you put some exception handling code around these operations so that you're guaranteed to dispose of your GDI+ objects. Good practice to close your streams too ... although to my knowledge MemoryStream object is managed so should close itself when GC'd.

Rabid
Oh should also mention, the likely reason for the warning for inclusion within ASP.NET is the potential for heavy request load and a rapid reduction in resources as has already been mentioned. You should probably throttle these requests, in which case.
Rabid