创建事件的数量是否有限制?

Is there a limit to the number of created events?

我正在 VS2015 上开发一个 C++14 Windows DLL,它可以在所有 Windows 版本 >= XP.

上运行

TL;DR

使用 CreateEvent 创建的事件数量是否有限制,当然名称不同?

背景

我正在写一个线程池class。 class界面很简单:

void AddTask(std::function<void()> task);

任务被添加到任务队列中,等待工作人员 (vector <thread>) 在可用时激活任务。

要求

在继续流程之前等待(阻止)任务一点点。意思是,某些 ThreadPool 的用户在调用 AddTask 后可能希望等待一段时间(比如 1 秒)让任务结束,然后再继续流程。如果任务还没有完成,他们仍然会继续流程。

问题

ThreadPool class 无法提供 Wait 接口。不是它的责任。

解决方案

  1. ThreadPool 将在任务完成后 SetEvent
  2. ThreadPool 的用户将等待(或不等待。取决于他们的需要)事件发出信号。

所以,我将 ThreadPool::AddTask 的 return 值从 void 更改为 int,其中 int 是一个唯一的任务 ID,本质上是任务完成时要被选中的事件的名称。

问题

我预计不会超过 ~500 个任务,但我担心创建数百个事件是不可能的,甚至是一种不好的做法。

所以有限制吗?或者更好的方法?

当然有 a 限制(如果不出意外;在某些时候系统会耗尽内存)。

实际上,每个进程的限制约为 1600 万。

您可以在此处阅读更多详细信息:https://blogs.technet.microsoft.com/markrussinovich/2009/09/29/pushing-the-limits-of-windows-handles/

你问错了问题。幸运的是,您提供了足够的背景知识来回答您真正的问题。但在此之前:

首先,如果您问一个进程可以打开或系统可以容纳的最大事件数是多少,您可能做错了非常非常错误的事情。询问进程可以打开的最大文件数或进程可以创建的最大线程数也是如此。

您可以创建 50、100、200、500、1000...但它会在哪里停止?如果您甚至考虑创建那么多您不得不询问限制的问题,那您就走错了路。

其次,答案取决于太多的实现细节:OS 版本、安装的 RAM 数量、注册表设置等等。其他程序 运行 也会影响 "limit"。

第三,即使您知道限制 - 即使您可以根据所有相关因素在运行时以某种方式计算它 - 它也不允许你可以做任何你现在不能做的事情

假设您发现限制是 L 并且您现在已经创建了 L 个事件。又一个任务进来了,你是做什么的?丢掉任务?在不发出事件信号的情况下执行任务?等到少于L个事件才创建事件开始执行任务?使进程崩溃?

任何你决定你可以在CreateEvent失败时做同样的事情。这一切都是毫无意义的。这又表明您问错了问题。


但也许你做的最错误的事情就是说 "the thread pool class can't provide wait because it's not its responsibility, so lets have the thread pool class provide an event for each task that the thread pool will signal when the task ends"(换句话说)。

看来到句尾忘记了开头的前提:这不是线程池的责任!

如果您想等待任务完成,请让任​​务本身在完成时发出信号。没有理由使线程池复杂化,因为有时有人想要等待任务。发出任务完成的信号是任务的工作:

event evt;                    ///// this
thread_pool.queue([evt] {
    // whatever
    evt.signal();             ///// and this
});
auto reason = wait(evt, 1s);
if (reason == timeout) {
    log("bummer");
}

event class 可以是任何你想要的 - Windows 事件,std::promisestd::future 对,或任何其他。

这很简单明了。

使线程池基础设施复杂化,白白占用宝贵的系统资源,即使在没有人监听的情况下也会发出同步原语信号,只是为了在您真正想要等待任务的少数情况下保存上面标记的两行代码说不过去。