如何捕获此 WPF 位图加载异常?
我正在开发一个使用 .NET 3.5 sp1 和 C# 从网络加载位图的应用程序。
加载代码如下所示:
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 异常来处理它,例如 这个问题。然而,这会严重扰乱我的程序的控制流程,如果可能的话我想避免这种情况。
我必须执行双源分配,因为似乎许多图像在 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()
I'm developing an application that loads bitmaps off of the web using .NET 3.5 sp1 and C#.
The loading code looks like:
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!");
}
and the code to load on bi_DownloadCompleted is:
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.");
}
}
Every so often, an image comes along that breaks the reader. I guess that's to be expected. However, rather than being caught by either of those try/catch blocks, the exception is apparently getting thrown outside of where I can handle it. I could handle it using global WPF exceptions, like this SO question. However, that will seriously mess up the control flow of my program, and I'd like to avoid that if at all possible.
I have to do the double source assignment because it appears that many images are lacking in width/height parameters in the places where the microsoft bitmap loader expects them to be. So, the first assignment appears to force the download, and the second assignment gets the dpi/image dimensions happen properly.
What can I do to catch and handle this exception?
If you'd like to replicate, try loading this image as the uri:
http://i.pbase.com/o2/26/519326/1/123513540.Yub8hciV.Longford12.jpg
The exception itself is:
System.ArgumentException in PresentationCore
Value does not fall within the expected range.
The inner exception is:
An invalid character was found in text context.
Stack trace:
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()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
此异常是图像中包含的颜色配置文件信息“损坏”的结果。如果您不关心此信息(或者想在异常后再次尝试解析),请使用 BitmapCreateOptions.IgnoreColorProfile 标志。
示例:
如果您需要了解更多信息,请查看 Scott Hanselman 的帖子。 (今天我们都通过电子邮件就这个问题进行了沟通。)
This exception is the result of 'broken' color profile information contained in the image. If you don't care about this information (or would like to try parsing again after exception), use the BitmapCreateOptions.IgnoreColorProfile flag.
Example:
If you're looking for more information, check out Scott Hanselman's post. (We were all in communication about this issue today, via email.)
这似乎有效:
BitmapFrame 有一个 DecodeFailed 事件,但我无法挂钩它,因为 BitmapFrame 在创建后被冻结。
This seems to work:
BitmapFrame has a DecodeFailed event, but I'm not able to hook it because the BitmapFrame is frozen after it's created.