如何捕获此WPF位图加载exception?

我正在开发一个应用程序,它使用.NET 3.5 sp1和C#从Web加载位图。

加载代码如下所示:

try { CurrentImage = pics[unChosenPics[index]]; bi = new BitmapImage(CurrentImage.URI); // BitmapImage.UriSource must be in a BeginInit/EndInit block. bi.DownloadCompleted += new EventHandler(bi_DownloadCompleted); AssessmentImage.Source = bi; } catch { System.Console.WriteLine("Something broke during the read!"); } 

并且在bi_DownloadCompleted上加载的代码是:

  void bi_DownloadCompleted(object sender, EventArgs e) { try { double dpi = 96; int width = bi.PixelWidth; int height = bi.PixelHeight; int stride = width * 4; // 4 bytes per pixel byte[] pixelData = new byte[stride * height]; bi.CopyPixels(pixelData, stride, 0); BitmapSource bmpSource = BitmapSource.Create(width, height, dpi, dpi, PixelFormats.Bgra32, null, pixelData, stride); AssessmentImage.Source = bmpSource; Loading.Visibility = Visibility.Hidden; AssessmentImage.Visibility = Visibility.Visible; } catch { System.Console.WriteLine("Exception when viewing bitmap."); } } 

每隔一段时间,就会出现一个图像,打破了读者。 我猜这是可以预料的。 但是,除了被这些try / catch块中的任何一个捕获之外,exception显然会被抛到我可以处理的地方之外。 我可以使用全局WPFexception来处理它,比如这个问题 。 但是,这会严重扰乱我程序的控制流程,如果可能的话,我想避免这种情况。

我必须进行双源分配,因为在微软位图加载器期望的地方,许多图像似乎缺少宽度/高度参数。 因此,第一个分配似乎强制下载,第二个分配使dpi /图像维度正确发生。

我该怎么做才能捕获并处理这个exception?

如果您想要复制,请尝试将此图像加载为uri:

 http://sofzh.miximages.com/c%23/123513540.Yub8hciV.Longford12.jpg 

例外本身是:

 System.ArgumentException in PresentationCore Value does not fall within the expected range. 

内在的例外是:

 An invalid character was found in text context. 

堆栈跟踪:

  at MS.Internal.HRESULT.Check(Int32 hr) at System.Windows.Media.Imaging.BitmapFrameDecode.get_ColorContexts() at System.Windows.Media.Imaging.BitmapImage.FinalizeCreation() at System.Windows.Media.Imaging.BitmapImage.OnDownloadCompleted(Object sender, EventArgs e) at System.Windows.Media.UniqueEventHelper.InvokeEvents(Object sender, EventArgs args) at System.Windows.Media.Imaging.LateBoundBitmapDecoder.DownloadCallback(Object arg) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) at System.Windows.Threading.Dispatcher.TranslateAndDispatchMessage(MSG& msg) at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Application.RunInternal(Window window) at LensComparison.App.Main() in C:\Users\Mark64\Documents\Visual Studio 2008\Projects\LensComparison\LensComparison\obj\Release\App.g.cs:line 48 at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() 

此exception是图像中包含的“损坏”颜色配置文件信息的结果。 如果您不关心此信息(或者想要在exception后再次尝试解析),请使用BitmapCreateOptions.IgnoreColorProfile标志。

例:

 BitmapImage i = new BitmapImage(); i.BeginInit(); i.CreateOptions |= BitmapCreateOptions.IgnoreColorProfile; i.UriSource = new Uri(@"http://www.bing.com/fd/hpk2/KiteFestival_EN-US2111991920.jpg"); i.EndInit(); 

如果您正在寻找更多信息,请查看Scott Hanselman的post 。 (我们今天通过电子邮件就此问题进行了沟通。)

这似乎有效:

 try { frame = BitmapFrame.Create(new Uri("http://sofzh.miximages.com/c%23/123513540.Yub8hciV.Longford12.jpg")); } catch { return; } 

BitmapFrame有一个DecodeFailed事件,但我无法挂钩它,因为BitmapFrame在创建后被冻结。