在C ++中创建/打开事件并检查它们是否被触发

时间:2009-03-01 18:23:27

标签: c++ windows multithreading events

我有两个线程使用事件进行同步。 在每个线程中,他们使用相同的调用:

::CreateEvent( NULL,TRUE,FALSE,tcEventName )

生产者线程是首先进行调用的线程,而消费者线程使调用最后,所以它在技术上是开放的,而不是创建事件......我假设。

但是,当在生产者线程中调用SetEvent时,永远不会在使用者线程中触发相同的事件(我正在使用WaitForMultipleObjects())

是否有工具可以告诉我事件是否真的被正确触发。

另外,当我在每个线程中调用CreateEvent()时,返回的句柄值对于每个线程都是不同的...它们应该是否相同?

有没有更好的方法来确保它能够正常运作?

这是在使用Visual Studio 2005的Windows XP上

编辑:我做了一些检查,发现在生产者线程中调用CreateEvent(第二个调用CreateEvent)将LastError设置为183(ERROR_ALREADY_EXISTS), 但是CreateEvent仍会返回事件的句柄......是什么给出的?如何错误已经存在但仍然返回一个句柄?或者它应该这样做?

4 个答案:

答案 0 :(得分:1)

如果您只在一个进程中使用多个线程,为什么不将事件句柄从一个传递到另一个?我知道创建的命名内核对象是为了在进程之间共享它们。

您也可以尝试使用OpenEvent函数打开已创建的事件。这可能会提供一些想法。

答案 1 :(得分:1)

根据CreateEvent的MSDN文档,

  

如果函数成功,则返回值是事件对象的句柄。如果在函数调用之前存在指定的事件对象,则该函数返回现有对象的句柄,GetLastError返回ERROR_ALREADY_EXISTS。

根据您的描述,我看不出您正在做什么的问题。我没有看到任何迹象表明你做错了什么。但是对于我来说,我通常使用CreateEvent()创建一次事件,然后将句柄传递给我希望由该事件发出信号的线程。但是你的方法在技术上没有任何问题。

你确实知道WaitForMultipleObjects()返回handle数组中第一个发信号句柄的索引,对吧?例如,如果您的命名事件是列表中的第二个事件,但是绝大多数时间(例如,通过快速操作的线程或发出信号但从未重置的手动重置事件)发出第一个句柄信号,WaitForMultipleObjects ()将始终返回WAIT_OBJECT_0。换句话说,您的消费者线程将永远不会看到您的命名事件被发出信号的事实,因为第一个句柄是“始终”信号。如果是这种情况,请将您的命名事件放在列表中。

您没有将WaitForMultipleObjects()的bWaitAll参数设置为TRUE,是吗?如果这样做,那么句柄数组中的所有句柄都会在函数返回之前发出信号。

谁为您的命名事件调用ResetEvent()?它应该是消费者。它不是被一些第三方线程意外调用的,是吗?

这些只是要仔细检查的一些事情。如果事件仍然没有按预期运行,请将WaitForMultipleObjects()替换为WaitForSingleObject(),以查看命名事件是否正确通知了使用者线程。

希望这有帮助。

答案 2 :(得分:0)

您的代码应该按照您的描述工作。如果在您尝试创建事件时该事件已存在,您将获得现有事件的句柄。

每个线程的句柄不同,所以如果它们不同(它们应该是),你不必担心。

我建议你简化一下,看看事情是否按照你期望的方式运作。你正在使用WaitForMultipleObjects()这一事实告诉我你还有其他的东西在继续。如果你认为它不起作用,那就去除其他东西,看看你是否能搞清楚。

答案 3 :(得分:0)

在单个进程中,您只需调用一次CreateEvent并共享所有线程中返回的句柄。

此外,除非您希望外部进程使用OpenEvent访问该事件,否则无需为该事件命名。实际上,如果您为活动命名,则只有一个程序副本能够成功调用CreateEvent。