退出应用程序时,使用UnsafeRegisterWaitForSingleObject失败并出现异常?

时间:2015-09-12 13:08:58

标签: c# process threadpool manualresetevent waithandle

我正在尝试使用*通知是否有某个应用退出。它至少在我想要的东西上起作用,但在我关闭主窗体之后,它会抛出异常:

  

SEHException:外部组件抛出异常

堆栈追踪:

/

以下是代码:

ThreadPool.UnsafeRegisterWaitForSingleObject

我甚至不需要等待调用回调,只需运行代码,然后关闭主窗体就会抛出异常。

有趣的是,如果使用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,或者我在这里错过了什么?

其他信息:面向.NET 4.0的Visual Studio 2010

谢谢。

1 个答案:

答案 0 :(得分:2)

wh.SafeWaitHandle = new SafeWaitHandle(p, true); 

这就是问题开始的地方。您现在有两个 SafeHandles包装相同的句柄。一个在Process对象中,另一个在ManualResetEvent对象中。不可避免地,其中一个总会失败。您的代码将始终崩溃,在这种情况下,它发生的原因是MRE的终结器首先运行。相反,你有50%的赔率,当Process Finalizer首先运行时就会发生。

第一种方法是不要这样做。您已经有了一个很好的活动,可以使用https://www.iso.org/obp/ui/#search。您甚至可以在正确的线程上运行它,以便MessageBox不会在另一个窗口后面消失,使用它的SynchronizingObject属性。

另一种方法是通过对DuplicateHandle进行pinvoking来复制句柄。的Bleh。或者只是解释为什么你首先滥用这个ManualResetEvent。 Process类是在.NET 1.0中设计的,如果其Handle属性为SafeHandle,则不会遇到此问题。但是它的IntPtr,他们再也无法解决这个问题了。通过从SafeHandle派生自己的类来修复它,不要在ReleaseHandle()重载中做任何事情。