2009-10-21 6 views
2

Opérations asynchrones avec E/S Les ports d'achèvement renvoient 0 octet transféré, bien que les opérations d'E/S fonctionnent comme prévu (mes tampons de lecture sont pleins).Opérations asynchrones avec des ports d'achèvement d'E/S retour 0 octets transférés

BYTE buffer[1024] = {0}; 
OVERLAPPED o = {0}; 
HANDLE file = CreateFile(
    _T("hello.txt"), 
    GENERIC_READ, 
    FILE_SHARE_READ, 
    NULL, 
    OPEN_EXISTING, 
    FILE_FLAG_OVERLAPPED, 
    NULL 
); 
HANDLE completion_port = CreateIoCompletionPort(
    file, 
    NULL, 
    0, 
    0 
); 
ReadFile(
    file, 
    buffer, 
    1024, 
    NULL, 
    &o 
); 

Dans le fil de travail:

DWORD numBytes = 0; 
LPOVERLAPPED po; 
GetQueuedCompletionStatus(
    completion_port, 
    &numBytes, 
    0, 
    &po, 
    INFINITE 
); 
GetOverlappedResult(file, &o, &numBytes, FALSE); 

Les deux fonctions renvoient 0 octets dans numBytes, mais buffer est remplissage. Est-ce que ce comportement est attendu?

Merci.

Répondre

3

Pour GetIoCompletionPort fonctionne correctement, vous devez spécifier un pointeur non NULL à une ULONG_PTR pour lui d'écrire la valeur « clé » à:

ULONG_PTR key; 

GetQueuedCompletionStatus(
    completion_port, 
    &numBytes, 
    &key, 
    &po, 
    INFINITE 
); 

Pour utiliser GetOverlappedResult avec succès, je crois que vous devez spécifier une poignée d'événement dans la structure OVERLAPPED (fortement recommandé dans tous les cas):

o.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); 

Appeler les deux successivement que vous étiez ne pas accomplir vraiment beaucoup - ils ont tous deux vous parler de la même e ings Cependant, si vous appelez les deux l'un après l'autre, vous devrez changer l'événement pour une réinitialisation manuelle en changeant le troisième paramètre à CreateEvent à TRUE. Je suppose que vous essayiez juste de voir si vous pouviez en faire un. Tout compte fait, j'utiliserais probablement GetQueuedCompletionStatus, et je m'en tiendrai là. Bien sûr, vous ferez généralement plus qu'appeler une fois et quitter. Vous appelez normalement dans une boucle, le traitement du tampon courant que vous avez lu, puis en appelant à nouveau ReadFile lire un autre tampon d'information, quelque chose comme ceci:

DWORD numBytes; 
LPOVERLAPPED po; 
while (GetQueuedCompletionStatus(completion_port, &numBytes, &key, &po, INFINITE)) { 
    std::cout << "\rRead: " << numBytes; // just to show it's set correctly. 
    process(buffer); 
    po->offset += sizeof(buffer); 
    ReadFile(file, buffer, sizeof(buffer), NULL, po); 
} 

Au moins dans un test rapide sur ma machine, ce a montré le nombre d'octets lus correctement (sizeof(buffer) jusqu'au dernier paquet, puis la taille restante du fichier).

+0

Oui, vous aviez raison sur le pointeur sur la touche. Vous aviez aussi raison dans votre hypothèse que j'ai essayé ces 2 fonctions pour voir si certaines d'entre elles fonctionnent :-). Merci. –

Questions connexes