windows 在 C++ 中创建/打开事件并检查它们是否被触发
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/600228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating/Opening Events in C++ and checking if they are fired
提问by Adam Haile
I have two threads that use an event for synchronization. In each thread they use the same call:
我有两个线程使用事件进行同步。在每个线程中,它们使用相同的调用:
::CreateEvent( NULL,TRUE,FALSE,tcEventName )
The producer thread is the one that makes the call first, while the consumer thread makes the call last, so it's technically opening, not creating the event... I assume.
生产者线程是第一个进行调用的线程,而消费者线程最后进行调用,所以它在技术上是开放的,而不是创建事件......我假设。
But, when SetEvent is called in the producer thread, the same event never gets triggered in the consumer thread (I'm using WaitForMultipleObjects())
但是,当在生产者线程中调用 SetEvent 时,消费者线程中永远不会触发相同的事件(我使用的是 WaitForMultipleObjects())
Is there a tool that can tell me if the event is actually getting triggered properly.
是否有工具可以告诉我事件是否真的被正确触发。
Also, when I call CreateEvent() in each thread, the returned handle value is different for each... should they be the same?
另外,当我在每个线程中调用 CreateEvent() 时,每个线程返回的句柄值都不同......它们应该相同吗?
Is there a better way to do this that will ensure it will work?
有没有更好的方法来做到这一点,以确保它会起作用?
This is on Windows XP using Visual Studio 2005
这是在 Windows XP 上使用 Visual Studio 2005
Edit:I did some more checking and found that calling CreateEvent in the producer thread (the second one to call CreateEvent) sets LastError to 183 (ERROR_ALREADY_EXISTS), however CreateEvent still returns a handle to the event...what gives? How can it error as already existing but still return a handle? Or is it supposed to do that?
编辑:我做了更多检查,发现在生产者线程(第二个调用 CreateEvent 的线程)中调用 CreateEvent 将 LastError 设置为 183 (ERROR_ALREADY_EXISTS),但是 CreateEvent 仍然返回事件的句柄......什么给出了?它怎么会因为已经存在而出错但仍然返回一个句柄?或者它应该这样做吗?
采纳答案by Matt Davis
According to the MSDN documentation for CreateEvent,
根据CreateEvent的 MSDN 文档,
If the function succeeds, the return value is a handle to the event object. If the named event object existed before the function call, the function returns a handle to the existing object and GetLastError returns ERROR_ALREADY_EXISTS.
如果函数成功,则返回值是事件对象的句柄。如果命名的事件对象在函数调用之前已存在,则该函数返回现有对象的句柄,GetLastError 返回 ERROR_ALREADY_EXISTS。
Based on your description, I don't see a problem with what you're doing. There's nothing I see to indicate you're doing something incorrectly. For me, though, I usually create the event once using CreateEvent() and then pass the handle to the thread(s) that I want to be signaled by that event. But there is nothing technically wrong with your approach.
根据您的描述,我认为您的操作没有问题。我没有看到任何迹象表明您做错了什么。但是,对我来说,我通常使用 CreateEvent() 创建一次事件,然后将句柄传递给我希望由该事件发出信号的线程。但是您的方法在技术上没有任何问题。
You do realize that WaitForMultipleObjects() returns the index of the first signaled handle in the handles array, right? For example, if your named event is the second one in the list, but the first handle is signaled the vast majority of the time (e.g., by a fast-acting thread or a manual reset event that is signaled but never reset), WaitForMultipleObjects() will always return WAIT_OBJECT_0. In other words, your consumer thread will never see the fact that your named event is signaled because the first handle is "always" signaled. If this is the case, put your named event first in the list.
您确实意识到 WaitForMultipleObjects() 返回 handles 数组中第一个发出信号的句柄的索引,对吗?例如,如果您的命名事件是列表中的第二个事件,但第一个句柄在绝大多数时间都发出信号(例如,通过快速执行的线程或手动重置事件发出信号但从未重置),WaitForMultipleObjects () 将始终返回 WAIT_OBJECT_0。换句话说,您的消费者线程永远不会看到您的命名事件已发出信号这一事实,因为第一个句柄“始终”发出信号。如果是这种情况,请将您命名的事件放在列表中的首位。
You don't happen to have the bWaitAll parameter to WaitForMultipleObjects() set to TRUE, do you? If you do, then all of the handles in the handles array have be signaled before the function returns.
您不会碰巧将 WaitForMultipleObjects() 的 bWaitAll 参数设置为 TRUE,对吗?如果这样做,则 handles 数组中的所有句柄都已在函数返回之前发出信号。
Who calls ResetEvent() for your named event? It should be the consumer. It's not accidentally being called by some third-party thread, is it?
谁为您的命名事件调用 ResetEvent()?应该是消费者。它不会被某个第三方线程意外调用,是吗?
These are simply some things to double-check. If the event still doesn't behave as you expect, replace the WaitForMultipleObjects() with WaitForSingleObject() to see if your named event properly signals the consumer thread.
这些只是需要仔细检查的一些事情。如果事件仍然没有按照您的预期运行,请将 WaitForMultipleObjects() 替换为 WaitForSingleObject() 以查看您的命名事件是否正确地向使用者线程发出信号。
Hope this helps.
希望这可以帮助。
回答by begray
If you just use several threads in one process, why don't you pass event handle from one to another? As I know named kernel objects created to share them between processes.
如果您只是在一个进程中使用多个线程,为什么不将事件句柄从一个传递到另一个?据我所知,创建命名内核对象是为了在进程之间共享它们。
Also you can try to use OpenEvent function to open already created event. This might give some ideas.
您也可以尝试使用 OpenEvent 函数打开已创建的事件。这可能会给出一些想法。
回答by jmucchiello
In a single process you only have to call CreateEvent once and share the handle returned in all threads.
在单个进程中,您只需调用一次 CreateEvent 并共享所有线程中返回的句柄。
Also, you do not need to name the Event unless you want external processes to access the event with OpenEvent. In fact, if you name the event, only one copy of your program will be able to call CreateEvent successfully.
此外,您不需要命名事件,除非您希望外部进程使用 OpenEvent 访问事件。事实上,如果您为事件命名,则只有您的程序的一个副本能够成功调用 CreateEvent。
回答by SoapBox
Your code should work as you've described it. If the event already exists when you try to create it, you will get a handle to the existing event.
您的代码应该像您描述的那样工作。如果在您尝试创建事件时该事件已经存在,您将获得现有事件的句柄。
Handles are different per-thread, so you needn't worry if they are different (they should be).
每个线程的句柄都不同,因此您不必担心它们是否不同(它们应该不同)。
I suggest you simplify a little bit to see if things are working the way you expect. The fact that you're using WaitForMultipleObjects() tells me you have other stuff going on. If you think it's not working, get rid of the other stuff and see if you can figure it out.
我建议您稍微简化一下,看看事情是否按您预期的方式工作。您使用 WaitForMultipleObjects() 的事实告诉我您还有其他事情要做。如果您认为它不起作用,请摆脱其他东西,看看是否可以解决问题。