C# 退出应用程序时,使用UnsaferRegisterWaitForSingleObject失败,出现异常?

C# 退出应用程序时,使用UnsaferRegisterWaitForSingleObject失败,出现异常?,c#,process,threadpool,manualresetevent,waithandle,C#,Process,Threadpool,Manualresetevent,Waithandle,我正在尝试使用ThreadPool.unasseregisterwaitforsingleobject通知某些应用程序是否退出。它至少能满足我的要求,但在我关闭主窗体后,它会抛出异常: SEHExException:外部组件引发了异常 堆栈跟踪: at Microsoft.Win32.SafeNativeMethods.CloseHandle(IntPtr handle) at Microsoft.Win32.SafeHandles.SafeProcessHandle.ReleaseHandle

我正在尝试使用
ThreadPool.unasseregisterwaitforsingleobject
通知某些应用程序是否退出。它至少能满足我的要求,但在我关闭主窗体后,它会抛出异常:

SEHExException:外部组件引发了异常

堆栈跟踪:

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
,或者我遗漏了什么

其他信息:VisualStudio2010,目标为.NET4.0

多谢各位

wh.SafeWaitHandle = new SafeWaitHandle(p, true); 
这就是问题的根源。您现在有两个SafeHandle正在包装同一个句柄。一个在Process对象中,另一个在ManualResetEvent对象中。不可避免地,他们中的一个总会输。您的代码总是会崩溃,在这种情况下,这是因为MRE的终结器首先运行。相反,当流程终结器第一次运行时,您有50%的可能性

第一种方法就是不要这样做。您已经有了一个很好的活动可以执行此操作,请使用。您甚至可以在正确的线程上运行它,以便MessageBox不会消失在另一个窗口后面,请使用它的SynchronizingObject属性


另一种方法是通过pinvoking DuplicateHandle复制句柄。呜呜。或者首先说明您滥用此事件的原因。Process类是在.NET 1.0中设计的,如果其Handle属性是SafeHandle,则不会出现此问题。但它是IntPtr,他们再也无法修复它了。通过从SafeHandle派生您自己的类来解决此问题,不要在ReleaseHandle()重载中执行任何操作。

谢谢您给出的好答案。事实上,我知道使用
Exited
事件,但在某种情况下,我发现它根本不起作用(尽管
EnableRaisingEvents
设置为true),所以我尝试找到一些解决方法来测试它。那我再检查一遍。