今回は、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;
}
もう一つの子スレッドです。何回か実行すると、実行のたびに結果が異なると思います。
Update Dec/19/2004 By Y.Kumei