では、さっそくプログラムを見てみましょう。
/* 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; }もう一つの子スレッドです。
何回か実行すると、実行のたびに結果が異なると思います。
Update Dec/19/2004 By Y.Kumei