我正在使用ThreadPool.UnsafeRegisterWaitForSingleObject
(以下称为RWFSO)异步等待Semaphore
。它返回RegisteredWaitHandle
,我不能轻易Unregister()
。我需要取消注册这些因为句柄保持对委托及其状态对象的引用,并且我的进程正在使用每个句柄泄漏内存。最终它们确实已经完成,但是这需要太长时间并且给GC带来太大的压力,使我的进程的私有内存使用量增加到1.8GB范围。我正在做很多异步请求。
信号量用于访问HttpWebRequest
的异步实现:BeginGetRequestStream
和BeginGetResponse
。如果我不使用信号量,它会一直告诉我“线程池上没有足够的自由线程”,因为它实现了它的愚蠢方式。如果我使用像semaphore.WaitOne()
这样的阻塞原语,那么我的线程池最终将被锁定,并且没有任何东西可以取得进展。
RWFSO返回RegisteredWaitHandle
,但这对我的调用线程没用,因为只有在等待完成时我才需要Unregister()
这个句柄;我没有取消方案。我不能只将RegisteredWaitHandle
实例传递给我的委托(通过传递给委托的状态对象上设置的带外字段),因为委托可以在控制甚至从RWFSO返回之前在另一个线程上完成
当且仅当等待完成时,我如何安全快速Unregister()
RegisteredWaitHandle
?
答案 0 :(得分:2)
只需通过任何适合您的机制将句柄传递给委托。如果在委托执行时句柄为空,则让委托旋转等待分配。不要担心使用的微量CPU时间,因为您可以将Thread.Yield
放入循环中。如果它困扰你,你可以使用锁。
或者你可以取消注册那里的句柄,让GC清理那些失去比赛的少数人。
答案 1 :(得分:0)
如果要绑定一个等待句柄的线程,为什么不同步发出HTTP请求呢?你正在做的实际上是每个请求绑定两个线程(如果我理解你的实现正确),而只是同步运行你的请求将每个请求一个线程(并且仍然可以使用信号量或约束线程池进行调节,如果你需要节制它。)