[英]Using UnsafeRegisterWaitForSingleObject failed with exception when exiting app?
I'm trying to use ThreadPool.UnsafeRegisterWaitForSingleObject
to notify if some app exits. 我正在尝试使用
ThreadPool.UnsafeRegisterWaitForSingleObject
通知某些应用程序是否退出。 It works at least at what I want but right after I close the main form, it throws the exception: 它至少可以满足我的要求,但是在我关闭主窗体后,它会抛出异常:
SEHException : External component has thrown an exception
SEHException:外部组件引发了异常
Stack trace: 堆栈跟踪:
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()
Here is the code: 这是代码:
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);
};
I don't even need to wait the callback to be invoked, just run the code and right after that closing the main form will throw the exception. 我什至不需要等待回调被调用,只需运行代码,然后在关闭主窗体后立即抛出异常。
Interestingly enough that if using OpenProcess
native function to get the process handle instead of using the Process
class like this: 有趣的是,如果使用
OpenProcess
本机函数来获取进程句柄,而不是使用像这样的Process
类:
//ProcessAccessFlags.Synchronize = 0x00100000
var p = OpenProcess(ProcessAccessFlags.Synchronize, false, 8524);
it then works OK without any exception but I'm not so sure if it's better to stick to managed wrapper as much as possible in this case. 然后它可以正常工作,没有任何异常,但是我不确定在这种情况下是否最好坚持使用托管包装器。 Also I would like to understand why this exception is thrown when using
Process
class. 我也想了解为什么在使用
Process
类时抛出此异常。 Looks like the Synchronize
flag (a required flag as documented) is what making it different between using OpenProcess
and the wrapper Process
. 看起来
Synchronize
标志(已记录为必需标志)使它在使用OpenProcess
和包装器Process
之间有所不同。 If so looks like Process
cannot replace OpenProcess
in this case or I missed something here? 如果看起来像
Process
在这种情况下无法替换OpenProcess
,或者我在这里错过了什么?
Other info: Visual Studio 2010, targeting .NET 4.0 其他信息:Visual Studio 2010,面向.NET 4.0
Thank you. 谢谢。
wh.SafeWaitHandle = new SafeWaitHandle(p, true);
That's where the problem started. 那是问题开始的地方。 You now have two SafeHandles that are wrapping the same handle.
现在,您有两个包装相同手柄的SafeHandle。 One in the Process object, another in the ManualResetEvent object.
一个在Process对象中,另一个在ManualResetEvent对象中。 Inevitably one of them will always lose.
不可避免地,其中之一会永远失败。 Your code will always crash, in this case it happened because the finalizer for the MRE ran first.
您的代码将始终崩溃,在这种情况下,它的发生是因为MRE的终结器首先运行。 You have 50% odds for the other way around, happens when the Process finalizer runs first.
反之,您有50%的几率发生在Process finalizer首先运行时。
The first approach is to just not do this. 第一种方法就是不这样做。 You already have an excellent event available to do this, use the Process.Exited event .
您已经有一个出色的事件可用于执行此操作,请使用Process.Exited事件 。 You can even run it on the right thread so that MessageBox doesn't disappear behind another window, use its SynchronizingObject property.
您甚至可以在正确的线程上运行它,以便MessageBox不会在另一个窗口后面消失,请使用其SynchronizingObject属性。
The other approach is duplicating the handle by pinvoking DuplicateHandle. 另一种方法是通过粉刺DuplicateHandle复制句柄。 Bleh.
的Bleh。 Or just address the reason why you abused this ManualResetEvent in the first place.
或者只是解决您首先滥用此ManualResetEvent的原因。 The Process class was designed in .NET 1.0, you wouldn't have had this problem if its Handle property was SafeHandle.
Process类是在.NET 1.0中设计的,如果它的Handle属性是SafeHandle,则不会出现此问题。 But its IntPtr, they couldn't fix that anymore.
但是它的IntPtr,他们再也解决不了了。 Fix it by deriving your own class from SafeHandle, don't do anything in the ReleaseHandle() overload.
通过从SafeHandle派生自己的类来对其进行修复,不要在ReleaseHandle()重载中执行任何操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.