Question:
Hey everyone,
I'm working on a thumbnail generator that also caches images in a NullBackingStore using the Ent. Lib. However, when I try to pull the images back out of the cache, it seems like the image is invalid (i.e. I can't retrieve a width or height value without throwing an exception. Here's the code for storing the image:
1 using (System.Drawing.Image im = System.Drawing.Image.FromStream((System.Net.WebRequest.Create(file).GetResponse().GetResponseStream())))
2 using (System.Drawing.Image tn = this.CreateThumbnail(im))
3 {
4 myCacheManager.Add("ThumbUrlKey:" + file, im, CacheItemPriority.Normal, null);
5
6 tn.Save(context.Response.OutputStream, ImageFormat.Jpeg);
7 }
And here's where it tries to pull the image out and send it to the browser:
1 using (System.Drawing.Image im = (System.Drawing.Image)myCacheManager["ThumbUrlKey:" + file])
2 using (System.Drawing.Image tn = this.CreateThumbnail(im))
3 {
4 tn.Save(context.Response.OutputStream, ImageFormat.Jpeg);
5 }
The exception occurs in line 5 of the CreateThumbnail function below:
1 private System.Drawing.Image CreateThumbnail (System.Drawing.Image src)
2 {
3 int maxSize = (int)this._sizeType;
4
5 int w = src.Width;
6 int h = src.Height;
7
8 if (w > maxSize)
9 {
10 h = (h * maxSize) / w;
11 w = maxSize;
12 }
13
14 if (h > maxSize)
15 {
16 w = (w * maxSize) / h;
17 h = maxSize;
18 }
19
20 return src.GetThumbnailImage(w, h, delegate() { return false; }, IntPtr.Zero);
21 }
I have to be missing something stupid. Does anyone have a suggestion?
Answer1:
Hi,
is the exception "Object reference not set to instance of an object"?
That means the item you get from cache has null refernce, and basically that could happen if cache is cleared (appdomain recycle, memory pressure, etc). In any case, you should check in code if the item lookuped from cache has null reference as that could happen in normal case too.
What's the size of these images? If they are larger, they can eat up memory easily and actually cause the pressure for asp.net to clear the cache. Any chance you could utilize caching elsewhere (output cache, IIS file caching etc)?
Answer2:
The exception is actually "Parameter is not valid." and crashes on the call to CreateThumbnail. I've been working on building another handler that uses a hardcoded cache key for testing purposes, and I get the save error. However, the test handler wraps the code in a "if (myCache.Contains(key)) " statement to make sure the cache is still valid. The image sizes themselves are no more than 50k a piece (and the thumbnails being stored around 4-8k range), plus, I'm currently only storing around 10 items in the cache.
My thought a few minutes ago was that maybe I was having a shallow object copy going into the cache, but Image supports IClonable, so I don't think it would that. Any suggestions?
Answer3:
That could mean the Image is disposed: http://blog.lavablast.com/post/2007/11/The-Mysterious-Parameter-Is-Not-Valid-Exception.aspx
And if you view your code, you have
using (System.Drawing.Image im = System.Drawing.Image.FromStream((System.Net.WebRequest.Create(file).GetResponse().GetResponseStream())))
2 using (System.Drawing.Image tn = this.CreateThumbnail(im))
3 {
4 myCacheManager.Add("ThumbUrlKey:" + file, im, CacheItemPriority.Normal, null);
5
6 tn.Save(context.Response.OutputStream, ImageFormat.Jpeg);
7 }
Which seems as if the Image object (im) is disposed by the time the outer using statement goes out of scope (using calls Dispose at the end for the object), just after the Image is added to the Cache.
Answer4:
You're my hero! After some research, I was able to convert the image over to a byte array and store that in the cache instead of the image object itself.
This helped with the conversions to and from the byte array (http://www.codeproject.com/KB/database/ObjectByteArrayConverter.aspx).
Thanks again for the help!