何时/如何注销RegisteredWaitHandle
本文关键字:注销 RegisteredWaitHandle 何注销 何时 | 更新日期: 2023-09-27 18:26:25
我使用ThreadPool.UnsafeRegisterWaitForSingleObject
(以下简称RWFSO)异步等待Semaphore
。它返回给我一个RegisteredWaitHandle
,而我不能轻易地返回Unregister()
。我需要注销这些,因为句柄保留了对委托及其状态对象的引用,而我的进程在每个句柄中都会泄漏内存。最终,它们确实完成了,但这需要太长的时间,给GC带来了太大的压力,使我的进程的私有内存使用量激增到1.8GB。我发出了很多异步请求。
信号量用于门控访问HttpWebRequest
的异步实现:BeginGetRequestStream
和BeginGetResponse
。如果我不使用信号量,它会一直告诉我"线程池中没有足够的可用线程",因为它的实现方式很愚蠢。如果我使用像semaphore.WaitOne()
这样的阻塞原语,那么我的线程池最终将死锁,并且不会有任何进展。
RWFSO返回一个RegisteredWaitHandle
,但这对我的调用线程没有用,因为只有在等待完成时,我才需要Unregister()
这个句柄;我没有取消的情况。我不能只将RegisteredWaitHandle
实例传递给我的委托(通过传递给委托的状态对象上设置的带外字段),因为在控制从RWFSO返回之前,委托可以在另一个线程上完成。
如何在等待完成时安全快速地Unregister()
和RegisteredWaitHandle
?
只需通过任何适合您的机制将句柄传递给委托即可。如果在执行委托时句柄为null,则让委托旋转以等待分配。不要担心使用的CPU时间太少,因为您可以将Thread.Yield
放入循环中。如果它困扰你,你可以用锁。
或者,您可以注销那里的句柄,并让GC清除少数输掉比赛的句柄。
如果要绑定一个等待句柄的线程,为什么不同步发出HTTP请求呢?实际上,您所做的是每个请求占用两个线程(如果我正确理解您的实现的话),而仅仅同步运行您的请求就需要每个请求占用一个线程(并且如果需要限制,仍然可以使用信号量或受约束的线程池进行调节)。