Изящно обрабатывать исключение загрузки изображения - PullRequest
0 голосов
/ 21 сентября 2010

Я загружаю изображения пользователей с помощью Silverlight 3. Все работает нормально, и я могу установить поток файлов на BitmapImage, и он будет обработан в порядке.

Проблема заключается в том, что, если я пытаюсь загрузить что-то, что не является изображением (например, .exe, который был переименован в .png), Silverlight аварийно завершает работу с System.Exception, который говорит "Катастрофический сбой". Документация MSDN бесполезно говорит, что так должно быть msdn link , и я должен прослушать событие ImageFailed (которое никогда не срабатывает).

Я что-то там пропустил или библиотека загружается из потока?

Код, который я загружаю из источника:

        var openFileDialog = new OpenFileDialog();
        openFileDialog.Filter = "*.jpg;*.jpeg;*.png|*.jpg;*.jpeg;*.png";
        openFileDialog.Multiselect = false;
        var showDialog = openFileDialog.ShowDialog();

        if (showDialog.HasValue && showDialog.Value)
        {
            using (var reader = openFileDialog.File.OpenRead())
            {
                var picture = new BitmapImage();

                picture.DownloadProgress += (o, e) => System.Threading.SynchronizationContext.Current.Send((oo) => System.Windows.Browser.HtmlPage.Window.Alert("Download progress: " + e.Progress), null);
                picture.ImageFailed += (o, e) => System.Threading.SynchronizationContext.Current.Send((oo) => System.Windows.Browser.HtmlPage.Window.Alert("Image failed: " + e.ErrorException), null);
                picture.ImageOpened += (o, e) => System.Threading.SynchronizationContext.Current.Send((oo) => System.Windows.Browser.HtmlPage.Window.Alert("Image opened: " + e.OriginalSource), null);

                picture.SetSource(reader); // BANG! here without any of the alerts showing up
            }
        }

1 Ответ

0 голосов
/ 21 сентября 2010

Это странно, но вы правы, это ведет себя так, даже в Silverlight 4.

Возможно, есть лучший вариант, но я нашел способ обойти эти исключения, которые иначе не могут быть обработаны, это изменить метод App.Application_UnhandledException (). Это будет работать для вас:

private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
    // Handle stupid image load exception.  Can't think of a better way to do it -- sorry.
    if (e.ExceptionObject is System.Exception && e.ExceptionObject.Message.Contains("HRESULT") && e.ExceptionObject.Message.Contains("E_UNEXPECTED"))
    {
        Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                MessageBox.Show("Error loading image.");
            });
        e.Handled = true;
        return;
    }

    // If the app is running outside of the debugger then report the exception using
    // the browser's exception mechanism. On IE this will display it a yellow alert 
    // icon in the status bar and Firefox will display a script error.
    if (!System.Diagnostics.Debugger.IsAttached)
    {

        // NOTE: This will allow the application to continue running after an exception has been thrown
        // but not handled. 
        // For production applications this error handling should be replaced with something that will 
        // report the error to the website and stop the application.
        e.Handled = true;
        Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
    }
}

Это хак, и мне это не нравится, но это лучше, чем необработанное исключение.

Кстати, вы действительно должны сообщить об ошибке Connect на это поведение. Это, безусловно, не соответствует «Закону наименьшего удивления». См. Сообщение Тима Хойера о том, как подать ошибку: http://timheuer.com/blog/archive/2010/05/03/ways-to-give-feedback-on-silverlight.aspx

...