WriteFile с проблемой порта завершения ввода-вывода - PullRequest
1 голос
/ 26 февраля 2012

У меня есть этот код, который в основном записывает в файл 5 раз, используя порты завершения ввода-вывода. Как вы уже догадались, это не очень хорошо работает. Проблема состоит в том, что я ожидаю, что «привет» будет записан в файл 5 раз, но всегда заканчивается записью только одного «привет». Я в замешательстве, потому что программа печатает «записано 5 байт» 5 раз, поэтому я предполагаю, что запись завершается нормально.

Кто-нибудь может увидеть проблему с этим?

#include <windows.h>
#include <stdio.h>

#define IOCP_NOMORE 3
#define IOCP_WRITE 1

HANDLE hWriteIoCp;

typedef struct _OVERLAPIOINFO {
    OVERLAPPED overlapped;
    HANDLE hFile;
} OVERLAPIOINFO;

HANDLE CreateNewCompletionPort()
{
    return CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
}

BOOL AssociateFileCompletionPort(HANDLE hIoPort, HANDLE hFile, DWORD completionKey)
{
    HANDLE h = CreateIoCompletionPort(hFile, hIoPort, completionKey, 0);
    return h == hIoPort;
}

DWORD WINAPI SaveFileWorkerThread(void *empty)
{
    ULONG_PTR completionKey;
    BOOL completionStatus;
    DWORD bytesTransferred;
    DWORD err;
    OVERLAPPED *overlap;
    OVERLAPIOINFO *info;

    for (;;)
    {
        completionStatus = GetQueuedCompletionStatus(hWriteIoCp, &bytesTransferred, &completionKey, &overlap, INFINITE);
        err = GetLastError();

        if (completionStatus) 
        {
            switch(completionKey)
            {
            case IOCP_WRITE:
                fprintf(stderr, "wrote %d bytes\n", bytesTransferred);
                break;

            case IOCP_NOMORE:
                fprintf(stderr, "done!");
                info = (OVERLAPIOINFO *) overlap;
                CloseHandle(info->hFile);
                free(info);
                break;

            }
        } 
        else 
        {
            if (overlap != NULL) 
                fprintf(stderr, "overlap not null");
            else 
                if (err != WAIT_TIMEOUT)
                    fprintf(stderr, "timeout");
        }
    }

}

int main()
{
    HANDLE hSaveFile;
    OVERLAPIOINFO *saveFileOverlap;
    char buf[] = "hello";

    hWriteIoCp = CreateNewCompletionPort();
    CreateThread(NULL, 0, SaveFileWorkerThread, NULL, 0, NULL);

    if ((hSaveFile = CreateFileA("C:\\received.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, 
        CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, NULL)) == INVALID_HANDLE_VALUE)
        fprintf(stderr, "unable to create file\n");

    saveFileOverlap = (OVERLAPIOINFO *) malloc(sizeof(*saveFileOverlap));
    memset(&(saveFileOverlap->overlapped), 0, sizeof(saveFileOverlap->overlapped));
    saveFileOverlap->hFile = hSaveFile;
    AssociateFileCompletionPort(hWriteIoCp, saveFileOverlap->hFile, IOCP_WRITE);

    for (int i = 0; i < 5; i++)
        if (!WriteFile(saveFileOverlap->hFile, buf, strlen(buf), NULL, &(saveFileOverlap->overlapped)))
            if (GetLastError() != ERROR_IO_PENDING)
                fprintf(stderr, "error writing file\n");

    PostQueuedCompletionStatus(hWriteIoCp, 0, IOCP_NOMORE, &(saveFileOverlap->overlapped));

    system("pause");
}

1 Ответ

4 голосов
/ 26 февраля 2012

вы пишете 5 раз в файл, но всегда в положение 0 - вам нужно установить смещение как часть lpOVERLAPPED параметра .

...