Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 何时/如何注销RegisteredWaitHandle_C#_.net_Windows_Threadpool - Fatal编程技术网

C# 何时/如何注销RegisteredWaitHandle

C# 何时/如何注销RegisteredWaitHandle,c#,.net,windows,threadpool,C#,.net,Windows,Threadpool,我正在使用ThreadPool.unasseregisterwaitforsingleobject(此后为RWFSO)异步等待信号量。它返回一个RegisteredWaitHandle,我无法轻松地Unregister()。我需要注销这些,因为句柄保留对委托及其状态对象的引用,而我的进程正在泄漏每个句柄的内存。最终它们会最终完成,但这需要花费太长的时间,给GC带来太大的压力,将进程的私有内存使用率膨胀到1.8GB的范围内。我提出了很多异步请求 该信号量用于对HttpWebRequest的异步实现

我正在使用
ThreadPool.unasseregisterwaitforsingleobject
(此后为RWFSO)异步等待
信号量。它返回一个
RegisteredWaitHandle
,我无法轻松地
Unregister()
。我需要注销这些,因为句柄保留对委托及其状态对象的引用,而我的进程正在泄漏每个句柄的内存。最终它们会最终完成,但这需要花费太长的时间,给GC带来太大的压力,将进程的私有内存使用率膨胀到1.8GB的范围内。我提出了很多异步请求

该信号量用于对
HttpWebRequest
的异步实现进行访问:
BeginGetRequestStream
BeginGetResponse
。如果我不使用信号量,它会一直告诉我“线程池中没有足够的空闲线程”,因为它的实现方式很愚蠢。如果我使用诸如
semaphore.WaitOne()
之类的阻塞原语,那么我的线程池最终将处于死锁状态,没有任何进展

RWFSO返回一个
RegisteredWaitHandle
,但这对我的调用线程没有用处,因为我需要
Unregister()
仅在等待完成时才返回此句柄;我没有取消的情况。我不能仅仅将
RegisteredWaitHandle
实例传递给我的委托(通过传递给委托的状态对象上设置的带外字段),因为委托可以在控制甚至从RWFSO返回之前在另一个线程上完成


如何安全快速地
Unregister()
RegisteredWaitHandle
s当且仅当其等待完成时?

如果要绑定等待句柄的线程,为什么不同步发出HTTP请求?实际上,您所做的是为每个请求占用两个线程(如果我正确理解您的实现的话),而同步运行您的请求将为每个请求占用一个线程(如果需要限制,仍然可以使用信号量或受约束的线程池进行调节).

只要通过任何适合您的机制将句柄传递给代理即可。如果在委托执行时句柄为null,则让委托旋转以等待分配。不要担心占用的CPU时间太少,因为您可以将
Thread.Yield
放入循环中。如果它困扰你,你可以用一把锁


或者,您可以注销那里的句柄,让GC清理掉少数输掉比赛的句柄。

我的意思是,这是对更广泛问题的一个回答。回答时可以说“嘿,你遇到麻烦了,因为你做错了”,而不是回答用户提出的确切问题。这就是为什么我们经常要求提供更多关于这种情况的上下文。“如果你要捆绑一个线程等待句柄”。。。否。RWFSO向操作系统注册一个回调,告诉它让一个委托排队调用工作线程池线程,以便在等待完成时完成工作。该方法几乎立即返回,并且不会阻塞调用它的线程。排队的工作只是启动真正异步I/O请求的一个简单调用。在我最初的评论之后,您已经更新了答案。。。只是说:)你试过P/调用
UnregisterWait
和variants(UnregisterWaitEx)了吗?没有,但是我会在什么引用上以及从哪里做?这是我面临的主要问题;尝试在等待完成后清理这些句柄。不幸的是,即使我
取消注册()
这些句柄,GC也不会回收它们,内存仍然泄漏。我已经用CLRProfiler.exe对此进行了测试,我看到一堆
RegisteredWaitHandle
对象在进程的生命周期内一直存在。@JamesDunne:如果在取消注册后将处理程序设置为
null
,会怎么样?是的,我在取消注册()之后将引用设置为
null
。没有区别。探查器能告诉您哪些对象保存引用吗?不,实际上,我只是看到
RegisteredWaitHandle
对象在进程结束时仍然处于活动状态。