Question

Opérations asynchrones avec les ports d'achèvement d'E / S renvoient 0 octet transféré, bien que les opérations d'E / S fonctionnent comme prévu (mes mémoires tampon de lecture sont saturées).

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 octet en numBytes, mais tampon est en cours de remplissage. Ce comportement est-il attendu?

Merci.

Était-ce utile?

La solution

Pour que GetIoCompletionPort fonctionne correctement, vous devez spécifier un pointeur non null sur un ULONG_PTR afin d'écrire la valeur 'key' dans:

ULONG_PTR key;

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

Pour utiliser GetOverlappedResult avec succès, je pense que vous devez spécifier un descripteur d'événement dans la structure OVERLAPPED (vivement recommandé dans tous les cas):

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

Appeler les deux à la suite, comme vous étiez, n’apporte pas grand-chose, ils vous disent tous les deux la même chose. Toutefois, si vous appelez les deux successivement, vous devrez modifier l'événement en une réinitialisation manuelle en définissant le troisième paramètre sur CreateEvent sur TRUE. J'imagine que vous essayiez juste de voir si vous pouviez en faire travailler un. Tout bien considéré, je n'utiliserais probablement que GetQueuedCompletionStatus , et en resterais là. Bien sûr, vous ferez généralement plus qu’appeler une fois et arrêter. Vous l’appelez normalement en boucle, en traitant le tampon actuel que vous avez lu, puis en appelant à nouveau ReadFile pour lire un autre tampon d’informations, 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, cela montrait le nombre d'octets lus correctement ( sizeof (tampon) jusqu'au dernier paquet, puis la taille restante du fichier).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top