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

时间:2017-08-08 06:11:32

标签: c++ windows multithreading events threadpool

我正在C++14上开发Windows VS2015个DLL,该DLL在所有Windows版本> = XP上运行。

TL; DR

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

背景

我正在写一个线程池类。 类接口很简单:

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

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

要求

在继续流程之前等待(阻止)一点任务。这意味着,在调用ThreadPool之后,AddTask的一些用户可能希望等待一段时间(比如1秒)以结束任务,然后再继续流程。如果任务尚未完成,他们将继续进行流程。

问题

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

解决方案

    任务完成后,
  1. ThreadPoolSetEvent
  2. ThreadPool的用户将等待(或不依赖于他们的需要)发出信号。
  3. 因此,我已将ThreadPool::AddTask的返回值从void更改为int,其中int是唯一的任务ID,基本上是.then(result => dispatch(departmentResult(result, types.DELETER))) .then(function(response) { if (response.status == 200){ NotificationManager.success('The department is deleted', 'Department Deleted ') } else if (response.status == 500) { NotificationManager.error('Sorry but this has already been used', 'ERROR! ') } else { NotificationManager.error('Sorry, something went wrong', 'ERROR! ') } }, function (error) { NotificationManager.error('Sorry but this has already been used', 'ERROR! ') }) .catch(function(error) { NotificationManager.error('Sorry but this has already been used', 'ERROR! ') // any error from "doing stuff" will show up here console.error(error); }); 的名称任务完成时要单挑的事件。

    问题

    我不期望超过500个任务,但我担心创造数百个事件是不可能的,甚至是不好的做法。

    那么有限制吗?还是更好的方法?

2 个答案:

答案 0 :(得分:1)

当然有 限制(如果没有别的;在某些时候系统内存不足)。

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

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

答案 1 :(得分:1)

你问的是错误的问题。幸运的是,你给了足够的背景来回答你的真实问题。但在我们开始之前:

首先,如果您询问进程可以打开或系统可以容纳的最大事件数是多少,那么您可能正在做一些非常错误的事情。同样可以询问进程可以打开的最大文件数是什么,或者进程可以创建的最大线程数是多少。

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

其次,答案取决于太多的实施细节:操作系统版本,安装的RAM数量,注册表设置等等。运行的其他程序也会影响“限制”。

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

让我们说你发现限制是 L ,你现在已经创建了 L 事件。另一个任务进来。你做什么?扔掉任务?执行任务而不发出事件信号?等到 L 事件少于 L 事件,然后才创建事件并开始执行任务?崩溃了吗?

无论什么你决定在CreateEvent失败时你可以做同样的事情。所有这一切都毫无意义。而这又是你提出错误问题的另一个迹象。

但也许你所做的最错误的事情就是说“线程池类不能提供wait,因为它不是它的责任,所以让线程池类为每个任务提供一个事件,线程池将在任务结束时发出信号“(在释义中)。

从句子结尾看,你从一开始就忘记了这个前提: 这不是线程池的责任!

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

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

event类可以是您想要的任何内容 - Windows事件,std::promisestd::future对,或其他任何内容。

这很简单明了。

使线程池基础结构变得复杂,无需占用宝贵的系统资源,并且即使在您实际想要等待任务的少数情况下没有人只是为了保存上面两个标记的代码行而发出信号同步原语也是不合理的