2011-04-04 112 views
1

im使用以下模式將win32異常轉換爲.NET異常。Marshal.ThrowExceptionForHR引發一個NotSupportedException

var result = A_KERNEL32_PINVOKE_CALL(); 
if (result == 0) 
{ 
    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 
} 

對於完整性的PInvoke調用下列之一:調用LoadLibrary,GetProcAddress的,SetWindowsHookEx函數。

這種運作良好,大部分的時候,拋出異常像這樣的:

System.ArgumentException:參數超出範圍。

在System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(的Int32的errorCode,IntPtr的errorInfo中)

但有時我得到以下異常:

System.NotSupportedException:該流不支持尋求操作。

在System.Net.ConnectStream.get_Position()

在System.Net.WebClient.WebClientWriteStream.get_Position()

在System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64的偏移量,的Int32原點)

在System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(的Int32的errorCode,IntPtr的errorInfo中)

我想不出一個理由的F或這個例外。請注意,堆棧跟蹤不像第一個異常那樣以ThrowExceptionForHRInternal開始。因此我認爲這可能是ThrowExceptionForHR方法本身的一個例外。

編輯:請注意,我沒有直接調用任何流方法。但是,代碼是在線程池線程中執行的,所以在使用Stream方法的同一線程中可能有其他代碼。

有什麼建議如何解決這個問題?

更新:我剛剛發現,該堆棧跟蹤

在System.Net.ConnectStream.get_Position()

在System.Net.WebClient.WebClientWriteStream.get_Position()

在System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64的偏移量,的Int32原點)

屬於到Image.S呼叫ave(Stream,Format)。有一個NotSupportedException被捕獲。這些代碼peaces是完全獨立的,但也許它們是在同一個線程池線程上執行的。

那麼爲什麼這個異常會影響我的代碼在另一種方法?

+0

當你得到NotSupportedException時,你能告訴我們你從Marshal.GetHRForLastWin32Error()得到什麼值嗎? – HABJAN 2011-04-04 15:35:53

+0

我試圖得到這個值,但這個問題很難重現。 – 2011-04-04 16:24:11

+0

hresult是-2147024809(Win32 /無效參數)。有時候會拋出一個ArgumentException,有時候是一個NotSupportedException。 (由於方法SetWindowsHookEx(path)。處理ArguementException) – 2011-04-07 08:43:01

回答

0

我不知道爲什麼ThrowExceptionForHRInternal嘗試操縱某些流。

雖然調用堆棧看起來很奇怪,但考慮不要直接從Web響應傳遞流,直接將繪圖函數傳遞給您的情況,但這會在您的情況下導致異常,但會首先將數據複製到內存流中。這可能會讓你看到什麼原始問題(因爲ThrowExceptionForHRInternal將不再失敗,試圖操縱一個流)。

+0

流方法調用不是我的代碼。我不知道如何影響這一點。 – 2011-04-04 16:17:13

1

現在我想,我濫用Marshal.ThrowExceptionForHR()方法。我想這並不打算用於Win32調用。我對行爲的解釋是,函數使用當前線程的上下文信息來收集有關異常的更多細節。 See this blog有類似的問題。

在我的情況下,問題可以通過創建我自己的ThrowExceptionForWin32ErrorCode(errorCode)方法來解決。

如果你有更好的解決方案,請繼續回答。

相關問題