【问题标题】:How can I reclaim thread handles allocated by the RPC runtime?如何回收 RPC 运行时分配的线程句柄?
【发布时间】:2013-01-22 13:24:13
【问题描述】:

一点背景:

我正在开发一个使用 RPC 通过网络进行通信的 Windows 程序。网络连接不断建立和断开。 RPC 调用是同步的,但有多个客户端线程同时运行。这些程序是对称的——也就是说,双方都充当客户端和服务器,并且运行完全相同的软件。它使用标准 Windows API 在 C++ 中实现。

问题:

Process Explorer 报告的线程句柄数会随着时间的推移而增加。看起来线程是由 RPC 运行时创建来处理请求的,但是当线程被回收时,句柄并不总是被清除。

这个数字会增加,尤其是在传输大量数据或同时发生许多呼叫时(这两个因素同时存在,我不确定哪个是相关的)。

一个活动服务器可以在几天内建立数千个未使用的线程句柄,而在任何时候都不会使用超过 20 个线程。

问题:

我可以做些什么来防止手柄数安装,因为我认为这可能会导致客户站点的稳定性问题?

【问题讨论】:

标签: c++ windows multithreading rpc handles


【解决方案1】:

嗯,令人惊讶的是,即使线程终止,也不会释放其所有资源。您必须在从 beginthreadex 收到的线程句柄上调用 CloseHandle() 或调用该事物的名称。另外,不要(!!!)使用 CreateThread(),请参阅 MSDN 文档。

还有一件事,虽然这不会导致您的问题,那就是线程的永久启动和终止。相反,使用线程池。此外,但这取决于您的实际设置,每个网络接口只需要一个线程用于 IO,每个 CPU 只需要一个线程用于计算。使用线程池,您可以轻松限制此数量。控制这些应该限制由线程创建/清理和上下文切换引起的开销。如果连接在网络 IO、CPU 和可能的磁盘 IO 甚至 UI 之间切换很多,这并不总是可行的。

【讨论】:

  • 问题是我不是打开这些线程的人——这一切都由 RPC 运行时在幕后处理。但是,我可以尝试在远程函数关闭之前调用 CloseHandle(),看看会发生什么。值得一试 - 感谢您的想法!
  • 不,线程似乎不可能关闭自己的现有句柄 - 替代方法是复制一个句柄并关闭它,但正如预期的那样,这完全没有任何作用。 RPC 运行时似乎确实使用了线程池,因为我经常看到线程被“重用”用于不同的调用。我现在将通过调用 AfxEndThread() 来进行实验,而不是从远程调用返回 - 也许这样可以更好地清理事情。
  • 这很糟糕,如果 RPC 系统没有重用线程但也没有结束它们,那就是那里的错误。唯一可能导致它出现在您的代码中的是,如果您设法永不返回,或者您设法以某种方式混淆 RPC 系统,例如通过通过抛出异常退出回调。尝试减少你在代码中所做的事情,看看它是否会消失。
猜你喜欢
  • 2012-04-06
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 2014-09-13
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多