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),所以我尝试找到一些解决方法来测试它。那我再检查一遍。