如何捕获此 WPF 位图加载异常?
Posted
技术标签:
【中文标题】如何捕获此 WPF 位图加载异常?【英文标题】:How do I catch this WPF Bitmap loading exception? 【发布时间】:2011-02-13 11:58:42 【问题描述】:我正在开发一个使用 .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 块中的任何一个捕获,而是被抛出了我可以处理的范围之外。我可以使用全局 WPF 异常来处理它,例如 this SO question。但是,这会严重扰乱我的程序的控制流程,如果可能的话,我想避免这种情况。
我必须进行双源分配,因为在 microsoft 位图加载器期望的位置,许多图像似乎缺少宽度/高度参数。因此,第一个分配似乎强制下载,第二个分配使 dpi/图像尺寸正确发生。
我能做些什么来捕捉和处理这个异常?
如果您想复制,请尝试将此图像加载为 uri:
http://i.pbase.com/o2/26/519326/1/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()
【问题讨论】:
碰到这个问题...我在使用与海报类似的技术从 Flickr 加载任意图像时遇到了同样的问题。 【参考方案1】:这似乎有效:
try
frame = BitmapFrame.Create(new Uri("http://i.pbase.com/o2/26/519326/1/123513540.Yub8hciV.Longford12.jpg"));
catch
return;
BitmapFrame 有一个 DecodeFailed 事件,但我无法挂钩它,因为 BitmapFrame 在创建后被冻结。
【讨论】:
【参考方案2】:此异常是图像中包含的“损坏”颜色配置文件信息的结果。如果您不关心此信息(或想在异常后再次尝试解析),请使用 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's post。 (今天我们都通过电子邮件就这个问题进行了沟通。)
【讨论】:
以上是关于如何捕获此 WPF 位图加载异常?的主要内容,如果未能解决你的问题,请参考以下文章