[英]Using UnsafeRegisterWaitForSingleObject failed with exception when exiting app?
我正在嘗試使用ThreadPool.UnsafeRegisterWaitForSingleObject
通知某些應用程序是否退出。 它至少可以滿足我的要求,但是在我關閉主窗體后,它會拋出異常:
SEHException:外部組件引發了異常
堆棧跟蹤:
at Microsoft.Win32.SafeNativeMethods.CloseHandle(IntPtr handle)
at Microsoft.Win32.SafeHandles.SafeProcessHandle.ReleaseHandle()
at System.Runtime.InteropServices.SafeHandle.InternalFinalize()
at System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
at System.Runtime.InteropServices.SafeHandle.Finalize()
這是代碼:
Load += (s, e) => {
var p = System.Diagnostics.Process.GetProcessById(8524).Handle;
var wh = new ManualResetEvent(false);
wh.SafeWaitHandle = new SafeWaitHandle(p, true);
var cl = ThreadPool.UnsafeRegisterWaitForSingleObject(
wh, new WaitOrTimerCallback((o, b) =>
{
MessageBox.Show("Exited!");
}), null, Timeout.Infinite, true);
};
我什至不需要等待回調被調用,只需運行代碼,然后在關閉主窗體后立即拋出異常。
有趣的是,如果使用OpenProcess
本機函數來獲取進程句柄,而不是使用像這樣的Process
類:
//ProcessAccessFlags.Synchronize = 0x00100000
var p = OpenProcess(ProcessAccessFlags.Synchronize, false, 8524);
然后它可以正常工作,沒有任何異常,但是我不確定在這種情況下是否最好堅持使用托管包裝器。 我也想了解為什么在使用Process
類時拋出此異常。 看起來Synchronize
標志(已記錄為必需標志)使它在使用OpenProcess
和包裝器Process
之間有所不同。 如果看起來像Process
在這種情況下無法替換OpenProcess
,或者我在這里錯過了什么?
其他信息:Visual Studio 2010,面向.NET 4.0
謝謝。
wh.SafeWaitHandle = new SafeWaitHandle(p, true);
那是問題開始的地方。 現在,您有兩個包裝相同手柄的SafeHandle。 一個在Process對象中,另一個在ManualResetEvent對象中。 不可避免地,其中之一會永遠失敗。 您的代碼將始終崩潰,在這種情況下,它的發生是因為MRE的終結器首先運行。 反之,您有50%的幾率發生在Process finalizer首先運行時。
第一種方法就是不這樣做。 您已經有一個出色的事件可用於執行此操作,請使用Process.Exited事件 。 您甚至可以在正確的線程上運行它,以便MessageBox不會在另一個窗口后面消失,請使用其SynchronizingObject屬性。
另一種方法是通過粉刺DuplicateHandle復制句柄。 的Bleh。 或者只是解決您首先濫用此ManualResetEvent的原因。 Process類是在.NET 1.0中設計的,如果它的Handle屬性是SafeHandle,則不會出現此問題。 但是它的IntPtr,他們再也解決不了了。 通過從SafeHandle派生自己的類來對其進行修復,不要在ReleaseHandle()重載中執行任何操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.