2009-06-07 6 views
1

Je souhaite utiliser un pool de threads pour initier/annuler des opérations de lecture superposées - en utilisant ReadFile() et CancelIo() respectivement - et gérer les événements de port d'achèvement lorsque les opérations de lecture sont terminées.E/S avec chevauchement: comment réveiller un thread sur un événement de port d'achèvement ou un événement normal?

  1. Tout thread peut lancer une opération de lecture
  2. Tout thread peut gérer un événement complet-lecture
  3. Seul le thread qui a initié une lecture peut l'annuler (ce qui est une limitation CancelIo())

Je ne suis pas sûr comment implémenter ceci. On appelle normalement GetQueuedCompletionStatus() pour attendre les événements de port d'achèvement et WaitForSingleObject() pour attendre les événements normaux, mais il n'est pas clair comment mélanger les deux. Si PostQueuedCompletionStatus() me permettrait de spécifier un fil spécifique pour se réveiller, je serais défini. Des idées?

MISE À JOUR: La solution doit être exécutée sur Windows XP. Malheureusement, cela exclut l'utilisation CancelIoEx() ou GetQueuedCompletionStatusEx().

Répondre

3

1 et 2 sont faciles, utilisez simplement le port d'achèvement d'E/S. Mais, comme vous avez trouvé 3 nécessite (avant Windows V6) le même fil.

Si vous utilisez Windows> = V6, GetQueuedCompletionStatusEx inclut une option modifiable qui provoquera le retour d'un APC sur le thread. Par conséquent, utilisez QueueUserAPC pour mettre en file d'attente un APC lorsque vous avez besoin de ce thread spécifique pour effectuer un autre travail. Vous aurez bien sûr besoin d'une file d'attente sûre pour fournir au thread interrompu des instructions sur ce qu'il faut annuler.

Si une compatibilité de version antérieure est requise, les choses deviennent plus difficiles. Possibilités:

  • Utilisez le paramètre de délai d'attente de GetQueuedCompletionStatus] (http://msdn.microsoft.com/library/aa364986) de revenir régulièrement pour vérifier en cas d'annulation.

  • Ou, plus probablement, de diviser le pool de threads en deux groupes. Threads qui initient et annulent les E/S. Le reste du temps, ces threads passent en attente d'être signalés pour effectuer l'une de ces actions. L'autre partie du pool attend les compléments d'E/S avec GetQueuedCompletionStatus.

Aucune de ces solutions n'est aussi belle, mais c'est toujours le problème avec les anciennes versions: elles manquent de fonctionnalités. Utilisez un APC non-op plutôt que de travailler dans l'APC afin que les limitations sur ce qui peut être fait dans un APC et ses problèmes inhérents avec la simultanéité soient évités. (Comme un APC est exécuté sur un thread, tous les verrous que ce thread contient sont conservés dans l'APC, tout état protégé sera arbitrairement incohérent.)

+1

Malheureusement, GetQueuedCompletionStatusEx() et CancelIoEx() nécessitent Windows Vista. Je vais mettre à jour la question pour noter que je suis à la recherche de solutions qui sont rétrocompatibles avec Windows XP. – Gili

+0

Oups, oublié que GQCSEx était également> = Vista ... mise à jour. – Richard

+0

Comment notifiez-vous le pool de threads "initier et annuler" qu'il doit appeler ReadFile()? Si j'utilise WaitOnMultipleObjects() où un seul événement indique un ReadFile en attente(), ne suis-je pas en train de vérifier toutes les lectures dans un seul thread? – Gili

Questions connexes