2009-03-01 2 views
1

J'ai deux threads qui utilisent un événement pour la synchronisation. Dans chaque thread ils utilisent le même appel:Création/ouverture d'événements en C++ et vérification de leur déclenchement

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

Le fil de producteur est celui qui fait l'appel d'abord, alors que le fil du consommateur fait l'appel dernier, il est donc techniquement ouverture, ne pas créer l'événement ... Je suppose.

Mais, quand SetEvent est appelé dans le fil de producteur, le même événement ne se déclenche dans le fil à la consommation (je l'utilise WaitForMultipleObjects())

est-il un outil qui peut me dire si l'événement est effectivement se déclencher correctement.

De même, lorsque j'appelle CreateEvent() dans chaque thread, la valeur du descripteur renvoyé est différente pour chaque ... doivent-ils être les mêmes?

Y a-t-il une meilleure façon de faire cela pour que cela fonctionne?

C'est sous Windows XP en utilisant Visual Studio 2005

Edit: je l'ai fait un peu plus de vérifier et a constaté que l'appel CreateEvent dans le fil de producteur (le second à appeler CreateEvent) met LastError à 183 (ERROR_ALREADY_EXISTS) , cependant CreateEvent retourne toujours un handle à l'événement ... que donne? Comment peut-il erreur comme existant déjà mais toujours retourner un handle? Ou est-ce censé faire ça?

Répondre

1

Selon la documentation MSDN pour CreateEvent,

Si la fonction réussit, la valeur de retour est une poignée à l'objet de l'événement. Si l'objet événement nommé existait avant l'appel de la fonction, la fonction renvoie un handle à l'objet existant et GetLastError renvoie ERROR_ALREADY_EXISTS.

Basé sur votre description, je ne vois pas de problème avec ce que vous faites. Il n'y a rien que je vois pour indiquer que vous faites quelque chose de mal. Pour ma part, cependant, je crée généralement l'événement une fois en utilisant CreateEvent(), puis je passe le handle au (x) thread (s) que je veux signaler par cet événement. Mais il n'y a rien de techniquement faux avec votre approche.

Vous réalisez que WaitForMultipleObjects() renvoie l'index du premier handle signalé dans le tableau de poignées, n'est-ce pas? Par exemple, si votre événement nommé est le deuxième dans la liste, mais le premier handle est signalé la plupart du temps (par exemple, par un thread rapide ou un événement de réinitialisation manuelle qui est signalé mais jamais réinitialisé), WaitForMultipleObjects() retournera toujours WAIT_OBJECT_0. En d'autres termes, votre thread consommateur ne verra jamais le fait que votre événement nommé est signalé parce que le premier handle est "toujours" signalé. Si c'est le cas, placez votre événement nommé en premier dans la liste.

Vous n'avez pas le paramètre bWaitAll à WaitForMultipleObjects() défini sur TRUE, n'est-ce pas? Si vous le faites, toutes les poignées du tableau de poignées doivent être signalées avant le retour de la fonction.

Qui appelle ResetEvent() pour votre événement nommé? Ce devrait être le consommateur. Ce n'est pas accidentellement appelé par un thread tiers, n'est-ce pas?

Ce sont simplement des choses à vérifier. Si l'événement ne se comporte toujours pas comme prévu, remplacez WaitForMultipleObjects() par WaitForSingleObject() pour voir si votre événement nommé signale correctement le thread consommateur.

Espérons que cela aide.

0

Votre code devrait fonctionner comme vous l'avez décrit. Si l'événement existe déjà lorsque vous essayez de le créer, vous obtiendrez un handle pour l'événement existant.

Les poignées sont différentes par thread, vous n'avez donc pas besoin de vous inquiéter si elles sont différentes (elles devraient l'être).

Je vous suggère de simplifier un peu pour voir si les choses fonctionnent comme vous le souhaitez. Le fait que vous utilisiez WaitForMultipleObjects() me dit que vous avez d'autres choses en cours. Si vous pensez que ça ne marche pas, débarrassez-vous des autres choses et voyez si vous pouvez le comprendre.

+0

Voir la question mise à jour ... –

+0

http://www.google.com/search?q=createevent <- premier résultat – SoapBox

1

Si vous utilisez simplement plusieurs threads dans un processus, pourquoi ne pas passer le handle d'événement de l'un à l'autre? Comme je sais, les objets du noyau nommés ont été créés pour les partager entre les processus.

Vous pouvez également essayer d'utiliser la fonction OpenEvent pour ouvrir un événement déjà créé. Cela pourrait donner quelques idées.

+0

j'ai essayé d'utiliser OpenEvent, mais avec les mêmes résultats –

+0

MSDN dit que CreateEvent définit la dernière erreur de ERROR_ALREADY_EXISTS exactement quand il retourne le handle déjà existant. Je vérifierais les noms d'objets avec plus de soin, peut-être que vous ouvriez un autre événement? Ou appel WaitForMultipleObjects. – begray

+0

Aussi, je ne sais pas avec certitude, mais à mon avis, le handle d'événement du même événement dans différents threads d'un processus doit être égal. Ils peuvent être différents dans différents processus. – begray

0

En un seul processus, vous n'avez qu'à appeler CreateEvent une seule fois et partager le handle renvoyé dans tous les threads.

De même, vous n'avez pas besoin de nommer l'événement sauf si vous souhaitez que des processus externes accèdent à l'événement avec OpenEvent. En fait, si vous nommez l'événement, une seule copie de votre programme pourra appeler CreateEvent avec succès.