Reputation: 1182
I have been developing a book viewing website that takes rather large images (upwards of 77+ megapixels) and scales them down before serving the image. It basically does the following algorithm:
Here is the code that halves an individual image. Note the use of BitmapImage:
Private Shared Function HalveImage(ByVal baseImagePath As String, ByVal baseWidth As Integer, ByVal baseHeight As Integer, ByVal newImagePath As String) As BitmapImage
Dim bi As New BitmapImage
With bi
.BeginInit()
.UriSource = New Uri(baseImagePath)
.DecodePixelWidth = baseWidth / 2 'only seting one DecodePixelXXX property preserves the aspect ratio
.EndInit()
End With
Dim enc As New System.Windows.Media.Imaging.JpegBitmapEncoder
With enc
.QualityLevel = 50
.Frames.Add(BitmapFrame.Create(bi))
End With
Using stream As New IO.FileStream(newImagePath, IO.FileMode.Create)
enc.Save(stream)
End Using
Return bi
End Function
This code was working fine on my dev machine, but when I installed it onto a server that server would suddenly stop caching images, after caching hundreds. The rest of the website continued to work fine. We found that the page caching code would eventually throw this exception every time it tried to create the BitmapImage object:
System.ComponentModel.Win32Exception: The system cannot find the file specified
at MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d)
at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
at MS.Win32.MessageOnlyHwndWrapper..ctor()
at System.Windows.Threading.Dispatcher..ctor()
at System.Windows.Threading.Dispatcher.get_CurrentDispatcher()
at System.Windows.Freezable..ctor()
at System.Windows.Media.Imaging.BitmapSource..ctor(Boolean useVirtuals)
at System.Windows.Media.Imaging.BitmapImage..ctor()
at RemoteFSTester.PageCachingThreadPool.WICResizer.CachePage(String id, Int32 item, Int32 index) in C:\Users\[...]\PageCachingThreadPool.vb:line 127
at RemoteFSTester.PageCachingThreadPool.CachePage(String id, Int32 item, Int32 index) in C:\Users\[...]\PageCachingThreadPool.vb:line 103
at RemoteFSTester.PageCachingThreadPool.WorkerMethod(PriorityThreadPoolDelegateArgs args) in C:\Users\[...]\PageCachingThreadPool.vb:line 91
at MDSA.Util.PriorityThreadpool.PriorityThreadPoolBase.Thread_DoWork(PriorityThreadPoolDelegateArgs args) in C:\Users\[...]\PriorityThreadPoolBase.vb:line 199
Even though the exception says 'cannot find the file specified', I can go straight to where the base image is located and open the file myself.
NOTE: Just to clarify, the server that houses the code and cached images is not the server that houses the base images. The code server grabs the file via a URI like '\servername\path\filename.jpg" from the base-image server.
After running some tests, the exceptions only occur when trying to open images on our IIS server via the BitmapImage object. The exception in BitmapImage happens whether I set the file path via UriSource or make a FileStream object and set the BitmapImage's StreamSource property to it. They don't occur if the files are opened via a FileStream object, nor do they occur if the files are opened via a console application. A console application using the BitmapImage object also runs without problem.
So, to finally ask my question, why does the server have trouble caching these images via ASP.NET while my dev machine has no problem?
Upvotes: 4
Views: 2796
Reputation: 1182
I found the solution to the problem here: Microsoft Connect Feedback
Long story short, I had to add the following code where it would run at the end of every thread process:
Dim myDispatcher As Dispatcher = Dispatcher.CurrentDispatcher
myDispatcher.BeginInvokeShutdown(DispatcherPriority.Normal)
Dispatcher.Run()
Upvotes: 4