第109章 オーバーラップ・ファイルI/O その3


今回は、2つのスレッドに同一のファイルを読み出させてみます。 単なる実験的なプログラムで、実用的な意味はありません。


では、さっそくプログラムを見てみましょう。

 /* overlap03.c */

#define MYFILE "test.txt"

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

unsigned __stdcall mythread0(void *);
unsigned __stdcall mythread1(void *);

OVERLAPPED ovl0, ovl1;

HANDLE hF0, hF1;
オーバーラップ構造体や、ファイルハンドルはグローバル変数にしてみました。
int main()
{
    HANDLE hFile, hTh[2];
    
    BOOL bRet;
    char szOrg[64], szBuf[64];
    DWORD dwWritten, thID0, thID1;
    int i;

    strcpy(szOrg, "No.%02d\r\n");
    hFile = CreateFile(MYFILE, GENERIC_WRITE,
        0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        printf("ファイルのオープンに失敗しました\n");
        return -1;
    }

    for (i = 0; i < 100; i++) {
        wsprintf(szBuf, szOrg, i);
        SetFilePointer(hFile, 0, NULL, FILE_END);
        bRet = WriteFile(hFile, szBuf, (DWORD)strlen(szBuf), &dwWritten, NULL);
        if (bRet == 0)
            printf("書き込み失敗です\n");
    }
    CloseHandle(hFile);
    
    hTh[0] = (HANDLE)_beginthreadex(NULL, 0, mythread0, NULL, CREATE_SUSPENDED, &thID0);
    hTh[1] = (HANDLE)_beginthreadex(NULL, 0, mythread1, NULL, CREATE_SUSPENDED, &thID1);

    printf("何かキーを打ってください\n");
    _getch();
    ResumeThread(hTh[0]);
    ResumeThread(hTh[1]);

    WaitForMultipleObjects(2, hTh, TRUE, INFINITE);
    CloseHandle(hTh[0]);
    printf("スレッドハンドル[0]をクローズしました\n");
    CloseHandle(hTh[1]);
    printf("スレッドハンドル[1]をクローズしました\n");
    return 0;
}
main関数です。まずは、読み出し用のテキストファイルを作ります。 これには、No.00(改行)No.01(改行)No.02...と書き込まれます。 改行は「\r\n」であることに注意してください。

次に2つの子スレッドをサスペンド状態で作っておきます。 ユーザーが何かキー入力をすると、スレッドが開始されます。 このスレッドが今作ったファイルを読み出します。

WaitForMultipleObjects関数で2つのスレッドが終了するのを待ちます。 2つとも終了したらスレッドハンドルをクローズしてプログラムを終了します。

unsigned __stdcall mythread0(void *lpx)
{
    BOOL bRet, bLError;
    static int nOst = 0;
    char buf[16];
    DWORD dwRead;

    hF0 = CreateFile(MYFILE, GENERIC_READ,
        FILE_SHARE_READ,
        NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if (hF0 == INVALID_HANDLE_VALUE) {
        printf("スレッド0:ファイルのオープンに失敗しました\n");
        return 1;
    }

    while (1) {
        ovl0.Offset = nOst;
        bRet = ReadFile(hF0, buf, 7, &dwRead, &ovl0);
        if (dwRead == 0) {
            printf("スレッド0読み出し終了\n");
            break;
        }
        if (!bRet) {
            bLError = GetLastError();
            if (bLError == ERROR_IO_PENDING) {
                WaitForSingleObject(hF0, INFINITE);
                if (GetOverlappedResult(hF0, &ovl0, &dwRead, TRUE)) {
                    printf("スレッド0:dpending...\n");
                }
            } else {
                printf("エラーです\n");
                CloseHandle(hF0);
                return 2;
            }    
        }
        printf("thread0:%s", buf);
        nOst += 7;
    }
    CloseHandle(hF0);

    return 0;
}
最初のスレッドです。

ファイル読み出し用でCreateFile関数を呼び出します。

オーバーラップI/Oを利用します。

読み出しは、1行ずつ行うようにしました。

1行読み出したら、ファイルポインタを7バイト進めます。 ファイルの終端を過ぎてしまったら、dwReadが0になるのでわかります。

unsigned __stdcall mythread1(void *lpx)
{
    BOOL bRet, bLError;
    static int nOst = 0;
    char buf[16];
    DWORD dwRead;

    hF1 = CreateFile(MYFILE, GENERIC_READ,
        FILE_SHARE_READ,
        NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if (hF1 == INVALID_HANDLE_VALUE) {
        printf("スレッド0:ファイルのオープンに失敗しました\n");
        return 1;
    }

    while (1) {
        ovl1.Offset = nOst;
        bRet = ReadFile(hF1, buf, 7, &dwRead, &ovl1);
        if (dwRead == 0) {
            printf("スレッド1読み出し終了\n");
            break;
        }
        if (!bRet) {
            bLError = GetLastError();
            if (bLError == ERROR_IO_PENDING) {
                WaitForSingleObject(hF1, INFINITE);
                if (GetOverlappedResult(hF1, &ovl1, &dwRead, TRUE)) {
                    printf("スレッド1:dpending...\n");
                }
            } else {
                printf("エラーです\n");
                CloseHandle(hF1);
                return 2;
            }    
        }
        printf("thread1:%s", buf);
        nOst += 7;
    }
    CloseHandle(hF1);

    return 0;
}
もう一つの子スレッドです。

何回か実行すると、実行のたびに結果が異なると思います。


[Index][総合Index] [Previous Chapter] [Next Chapter]

Update Dec/19/2004 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。