这是 WPF SplashScreen 类中的一个错误。在 .NET 4.6 BitmapHandle 中仍然存在一个 SafeHandle 类,它的ReleaseHandle()方法如下所示:
protected override bool ReleaseHandle()
{
return UnsafeNativeMethods.DeleteObject(handle);
}
这是非常正确的,它确保 GDI 位图对象无论发生什么都被正确销毁。该错误存在于SplashScreen.DestroyResources()方法中,它帮助太大了:
private void DestroyResources()
{
//...
if (_hBitmap != null && !_hBitmap.IsClosed)
{
UnsafeNativeMethods.DeleteObject(_hBitmap.MakeHandleRef(null).Handle);
_hBitmap.Close();
_hBitmap = null;
}
//...
}
两个电话DeleteObject
,太多了。调试器有一个 MDA(托管调试助手)来监视此类错误,它会看到 ReleaseHandle() 失败并介入。您通常不会看到这一点,因为(不明智地)MDA 默认情况下是关闭的。调试 > 异常 > 托管调试助手 > ReleaseHandleFailed。取消勾选它以停止接收通知。
像这样的错误非常讨厌,它们打开了处理回收攻击的大门。然而,它实际上可被利用的几率非常低,Close() 调用紧跟 DeleteObject() 调用之后,位图并不是特别危险 :) 技术上可能发生事故,您必须让另一个线程同时创建 GDI 对象时间,这在 WPF 应用程序中并不经常发生。
您可以在 connect.microsoft.com 上提交错误,指向此 Q+A 的链接就足够了。