ASP.NET выдает Win32Exception при создании BitmapImage, не может найти указанный файл - PullRequest
4 голосов
/ 25 января 2012

Я занимаюсь разработкой веб-сайта для просмотра книг, который берет довольно большие изображения (более 77 мегапикселей) и масштабирует их перед тем, как отправить изображение. Это в основном делает следующий алгоритм:

  1. Если запрошенная книга уже была кэширована, подайте кэшированные изображения.
  2. Если книга не была кэширована, добавьте книгу в наш пул потоков кэширования книг.
  3. Пул потоков кэширования книг добавляет страницу каждой книги в наш пул потоков кэширования страниц.
  4. Пул потоков кэширования страниц кэширует изображение (расположенное на сервере в нашей локальной сети), наполовину снова и снова уменьшая изображение до тех пор, пока мы не уменьшим кэшированные версии образа в 2, 4, 8, 16, 32 и 64 раз. .

Вот код, делящий пополам отдельное изображение. Обратите внимание на использование 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

Несмотря на то, что исключение говорит «не удается найти указанный файл», я могу сразу перейти к тому месту, где находится базовое изображение, и открыть файл самостоятельно.

ПРИМЕЧАНИЕ. Чтобы уточнить, сервер, на котором размещены код и кэшированные изображения, не является сервером, на котором размещены базовые образы. Сервер кода захватывает файл через URI, например «\ servername \ path \ filename.jpg», с сервера базовых изображений.

После выполнения некоторых тестов исключения возникают только при попытке открыть изображения на нашем IIS-сервере через объект BitmapImage. Исключение в BitmapImage происходит, независимо от того, устанавливаю ли я путь к файлу через UriSource или создаю объект FileStream и устанавливаю для него свойство StreamSource для BitmapImage. Они не появляются, если файлы открываются через объект FileStream, и не возникают, если файлы открываются через консольное приложение. Консольное приложение, использующее объект BitmapImage, также запускается без проблем.

Итак, чтобы наконец задать мой вопрос, почему у сервера возникают проблемы с кэшированием этих изображений через ASP.NET, а у моей машины нет проблем?

1 Ответ

4 голосов
/ 25 января 2012

Я нашел решение проблемы здесь: Обратная связь Microsoft Connect

Короче говоря, мне пришлось добавить следующий код, где он будет запускаться в конце каждого процесса потока:

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