使用以下模式将win32异常转换为.NET异常。
var result = A_KERNEL32_PINVOKE_CALL();
if (result == 0)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
为了完整性,pinvoke调用是以下之一:LoadLibrary,GetProcAddress,SetWindowsHookEx。
大部分时间都可以正常运行,抛出类似这样的异常:
System.ArgumentException:参数超出范围。
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode,IntPtr errorInfo)
但有时我得到以下例外:
System.NotSupportedException:此Stream不支持搜索操作。
在System.Net.ConnectStream.get_Position()
在System.Net.WebClient.WebClientWriteStream.get_Position()
at System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64 offset,Int32 origin)
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode,IntPtr errorInfo)
我想不出这个例外的原因。请注意,堆栈跟踪不像ThrowExceptionForHRInternal那样以第一个异常开头。因此我认为这可能是ThrowExceptionForHR方法本身的一个例外。
编辑:请注意,我没有直接调用任何Stream方法。但是代码是在线程池线程中执行的,因此使用Stream方法可能在同一个线程中有其他代码。
有关如何解决此问题的任何建议吗?
更新:我刚刚发现,堆栈跟踪
在System.Net.ConnectStream.get_Position()
在System.Net.WebClient.WebClientWriteStream.get_Position()
at System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64 offset,Int32 origin)
属于对Image.Save(Stream,Format)的调用。有一个NotSupportedException被捕获。这些代码和平是完全独立的,但也许它们是在同一个线程池线程上执行的。
那么为什么这个异常会在另一个方法中影响我的代码呢?
答案 0 :(得分:2)
到目前为止,我认为,我误用了Marshal.ThrowExceptionForHR()方法。我想它不打算用于Win32调用。我对行为的解释是,该函数使用当前线程的上下文信息来收集有关异常的更多细节。 See this blog针对类似问题。
在我的情况下,可以通过创建我自己的ThrowExceptionForWin32ErrorCode(errorCode)方法来解决该问题。
如果你有更好的解决方案,请继续回答。
答案 1 :(得分:0)
我不知道为什么ThrowExceptionForHRInternal会尝试操纵某些流。
虽然调用堆看起来很奇怪,但考虑不直接将流从Web响应传递给绘图函数,这些函数在您的情况下似乎会导致异常,但首先将数据复制到内存流。这可能会让您看到原始问题是什么(因为ThrowExceptionForHRInternal将不再尝试操作流失败)。