我有两个线程使用事件进行同步。 在每个线程中,他们使用相同的调用:
::CreateEvent( NULL,TRUE,FALSE,tcEventName )
生产者线程是首先进行调用的线程,而消费者线程使调用最后,所以它在技术上是开放的,而不是创建事件......我假设。
但是,当在生产者线程中调用SetEvent时,永远不会在使用者线程中触发相同的事件(我正在使用WaitForMultipleObjects())
是否有工具可以告诉我事件是否真的被正确触发。
另外,当我在每个线程中调用CreateEvent()时,返回的句柄值对于每个线程都是不同的...它们应该是否相同?
有没有更好的方法来确保它能够正常运作?
这是在使用Visual Studio 2005的Windows XP上
编辑:我做了一些检查,发现在生产者线程中调用CreateEvent(第二个调用CreateEvent)将LastError设置为183(ERROR_ALREADY_EXISTS), 但是CreateEvent仍会返回事件的句柄......是什么给出的?如何错误已经存在但仍然返回一个句柄?或者它应该这样做?
答案 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。