【问题标题】:ASP.NET Throws Win32Exception when creating BitmapImage, cannot find file specifiedASP.NET 创建 BitmapImage 时抛出 Win32Exception,找不到指定的文件
【发布时间】:2012-01-24 23:03:22
【问题描述】:

我一直在开发一个图书浏览网站,该网站拍摄相当大的图像(超过 77+ 兆像素)并在提供图像之前将它们缩小。它基本上执行以下算法:

  1. 如果请求的图书已被缓存,则提供缓存的图像。
  2. 如果图书尚未缓存,请将图书添加到我们的图书缓存线程池中。
  3. 图书缓存线程池将每本书的页面添加到我们的页面缓存线程池中。
  4. 页面缓存线程池通过反复减半图像来缓存图像(位于我们 LAN 上的服务器上),直到我们将图像的缓存版本减少 2x、4x、8x、16x、32x 和 64x .

这是将单个图像减半的代码。注意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

这段代码在我的开发机器上运行良好,但是当我将它安装到服务器上时,服务器会在缓存数百张图像后突然停止缓​​存图像。该网站的其余部分继续正常工作。我们发现页面缓存代码每次尝试创建 BitmapImage 对象时最终都会抛出这个异常:

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

即使异常显示“找不到指定的文件”,我也可以直接转到基础映像所在的位置并自己打开文件。

注意:为了澄清,存放代码和缓存图像的服务器不是存放基本图像的服务器。代码服务器通过诸如“\servername\path\filename.jpg”之类的 URI 从基础图像服务器获取文件。

运行一些测试后,只有在尝试通过 BitmapImage 对象在我们的 IIS 服务器上打开图像时才会出现异常。无论我是通过 UriSource 设置文件路径还是创建 FileStream 对象并将 BitmapImage 的 StreamSource 属性设置为它,BitmapImage 中的异常都会发生。如果文件是通过 FileStream 对象打开的,它们就不会发生,如果文件是通过控制台应用程序打开的,它们也不会发生。使用 BitmapImage 对象的控制台应用程序也可以正常运行。

那么,最后问我的问题,为什么服务器无法通过 ASP.NET 缓存这些图像,而我的开发机器却没有问题?

【问题讨论】:

  • 在 .net 的各个领域都有类似的问题,内置“loadFromFile”方法,通常与权限或锁定有关。通常是断断续续的,而且几乎总是掩盖失败的真正原因。因此,我们实施了始终使用 FileStream 并传入显式 FileMode 和 FileAccess 参数的策略。摆脱了一大堆有趣的事情。
  • Tony,感谢您的建议,但是将 FileStream 传递给 BitmapImage 对象(通过设置 StreamSource 而不是 UriSource)不会改变任何事情。
  • 你说如果你通过 FileStream 对象打开它会起作用吗?
  • 如果我将每个文件作为 FileStream 对象打开,我可以遍历基本图像,但如果我将每个文件作为 FileStream 对象打开,然后将 BitmapImage 的 StreamSource 属性设置为 FileStream 对象,则不能。如果它以这种方式工作,我将只使用 StreamSource 而不是 UriSource 并称之为一天。
  • 啊,明白了。是不是很头疼。您是否考虑过使用 FileStream 将文件移动到缓存中(或暂时处理缓存),然后在本地处理位图图像

标签: asp.net iis bitmapimage


【解决方案1】:

我在这里找到了问题的解决方案: Microsoft Connect Feedback

长话短说,我必须在每个线程进程结束时添加以下代码:

Dim myDispatcher As Dispatcher = Dispatcher.CurrentDispatcher
myDispatcher.BeginInvokeShutdown(DispatcherPriority.Normal)
Dispatcher.Run()

【讨论】:

  • Sheesh Dispatcher 被设计成一个进程,只要有我们正在快速耗尽的资源,它就会运行。让你想尖叫不是吗?
猜你喜欢
  • 2011-10-07
  • 2023-04-02
  • 1970-01-01
  • 2016-08-19
  • 2021-11-25
  • 1970-01-01
  • 2012-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多