I'm loading user images using Silverlight 3.
Everything works fine and I can set the file stream to a BitmapImage
and it gets rendered OK.
The problem is that if I try to load something that's not an image (like a .exe that's been renamed to .png) Silverlight crashes with a System.Exception
that says "Catastrophic failure".
The MSDN documentation unhelpfully says that it should be so there msdn link and I should listen to the Ima开发者_Go百科geFailed
event (which never gets fired).
Am I missing something there or is the library broken when loading from a stream?
The code I've got loading the image from the source:
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
}
}
That's weird, but you're right, it does behave that way, even on Silverlight 4.
There may be a better option, but one way I've found to work around these exceptions that can't otherwise be handled is to modify the App.Application_UnhandledException() method. This would work for you:
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); });
}
}
It's a hack and I don't like it, but it's better than an unhandled exception.
BTW, you really ought to file a Connect bug on this behavior. It quite certainly fails the "Law of Least Astonishment". See Tim Heuer's post on how to get the bug filed: http://timheuer.com/blog/archive/2010/05/03/ways-to-give-feedback-on-silverlight.aspx
精彩评论