우선 코드가 길고...... 저에겐 빌더6만 깔려 있어서 실행은 못해보지만...
dwWaitResult = WaitForMultipleObjects(THREAD_COUNT, handle, TRUE, INFINITE);
if (WAIT_OBJECT_0 + THREAD_COUNT - 1 == dwWaitResult) {
Label4->Caption = TimeToStr(Time());
}
else {
//Label4->Caption = "fail"; //<--------이쪽으로 들어옵니다. 왜 그럴까요?????
Label4->Caption = TimeToStr(Time());
}
특정 쓰레드가 시그널 상태가 되면, 그 갯수가 아닌 해당 스레드의 순서? 번호? 가 넘어 옵니다. 하지만 bsWait부분이 TRUE라면
WaitForMultiple..... 이 전체를 기다리다가 기다리는 모든것이 시그널 상태가 된다면
WAIT_OBJECT_0
가 넘어올겁니다.
TRUE를 FALSE로 바꾼다면, 시그널된 쓰레드의 WAIT_OBJECT_0 + 번호 가 넘어 오구요.
헬프 내용입니다.
If bWaitAll is TRUE, the return value indicates that the state of all specified objects is signaled.
leo21c 님이 쓰신 글 :
: Thread 테스트 프로그래밍 중에 WaitForMultipleObjects()함수 리턴값이 원한는 값이 나오지 않습니다.
: Thread 공부중입니다.
: WaitForMultipleObjects()함수는 생성된 Thread가 모두 종료 되면 그 개수를 리턴하는 것으로 알고 있습니다.
:
: 테스트 프로그램은 100개의 파일을 100개의 각각의 Thread가 jpg를 읽어 색을 반전하고 다시 다른이름으로
: 저장하도록 했습니다.
:
: serial file open and convert, resave 하는 루틴과 thread로 처리한 루틴의 처리 시간을 비교하기 위해서
: 만들었습니다.
:
: 고수님의 조어 부탁드립니다.
:
: WaitForMultipleObjects()의 리턴 값이 WAIT_OBJECT_0 + THREAD_COUNT - 1이 되지 않고 다르다고 나옵니다.
:
: 파일이 각각 다른기 때문에 파일을 처리하고, 접근(읽고, 쓰기) 할 때 동기화가 필요없다고 생각했습니다.
:
: 소스는 아래와 같습니다.
:
: 프로젝트는 첨부로 올렸습니다.
:
: ///////////////////////////////////////////////////////////////////////////////////////////////////
: //test.h
: //--------------------------------
: //---------------------------------------------------------------------------
:
: #ifndef Unit1H
: #define Unit1H
: //---------------------------------------------------------------------------
: #include <Classes.hpp>
: #include <Controls.hpp>
: #include <StdCtrls.hpp>
: #include <Forms.hpp>
: //---------------------------------------------------------------------------
: class TForm1 : public TForm
: {
: __published: // IDE-managed Components
: TButton *Button1;
: TButton *Button2;
: TLabel *Label1;
: TLabel *Label2;
: TLabel *Label3;
: TLabel *Label4;
: void __fastcall Button1Click(TObject *Sender);
: void __fastcall Button2Click(TObject *Sender);
: private: // User declarations
: public: // User declarations
: int check[30];
: int index;
: AnsiString defaultDir;
:
: __fastcall TForm1(TComponent* Owner);
:
: void __fastcall ConvertImage(Graphics::TBitmap* bitmap, int index, int kind = 0);
: };
: //---------------------------------------------------------------------------
: class ImpThread : public TThread
: {
: private:
: int Index;
: AnsiString defaultDir;
: protected:
: void __fastcall Execute();
: public:
:
: __fastcall ImpThread(int index);
: };
: //---------------------------------------------------------------------------
: extern PACKAGE TForm1 *Form1;
: //---------------------------------------------------------------------------
: #endif
: ///////////////////////////////////////////////////////////////////////////////////////////////////
:
:
: ///////////////////////////////////////////////////////////////////////////////////////////////////
: //test.cpp
: ///////////////////////////////////////////////////////////////////////////////////////////////////
:
: //---------------------------------------------------------------------------
:
: #include <vcl.h>
: #pragma hdrstop
:
: #include "test.h"
: #include "JPEG.hpp"
: //---------------------------------------------------------------------------
: #define THREAD_COUNT 100
: //---------------------------------------------------------------------------
: #pragma package(smart_init)
: #pragma resource "*.dfm"
: TForm1 *Form1;
: CRITICAL_SECTION crit;
: //---------------------------------------------------------------------------
: __fastcall TForm1::TForm1(TComponent* Owner)
: : TForm(Owner)
: {
: defaultDir = "C:\\Temp_Image\\";
:
: InitializeCriticalSection(&crit);
: }
: //---------------------------------------------------------------------------
: void __fastcall TForm1::ConvertImage(Graphics::TBitmap* bitmap, int index, int kind)
: {
: EnterCriticalSection(&crit);
:
: if (kind == 1) index++;
:
: AnsiString filename = defaultDir + index;
: filename += ".jpg";
: TJPEGImage *pJpeg = new TJPEGImage();
: pJpeg->LoadFromFile(filename);
:
: bitmap->Assign(pJpeg);
:
: Byte* ptr;
: unsigned char pBuffR;
: unsigned char pBuffG;
: unsigned char pBuffB;
:
: for (int y = 0; y < bitmap->Height; y++) {
: ptr = (Byte *)bitmap->ScanLine[y];
: for (int x = 0; x < bitmap->Width; x++) {
: pBuffB = ptr[3*x];
: pBuffG = ptr[3*x+1];
: pBuffR = ptr[3*x+2];
:
: ptr[3*x] = 255 - pBuffB;
: ptr[3*x+1] = 255 - pBuffG;
: ptr[3*x+2] = 255 - pBuffR;
: }
: }
:
: pJpeg->Assign(bitmap);
:
: filename = defaultDir;
: if (kind == 0) filename += "normal\\";
: else filename += "thread\\";
: filename += index;
: filename += "_r.jpg";
:
: pJpeg->SaveToFile(filename);
:
: delete pJpeg;
:
: LeaveCriticalSection(&crit);
: }
: //---------------------------------------------------------------------------
: void __fastcall TForm1::Button1Click(TObject *Sender)
: {
: Label1->Caption = TimeToStr(Time());
:
: Graphics::TBitmap* bitmap = NULL;
: for (int i = 1; i < THREAD_COUNT + 1; i++) {
: bitmap = new Graphics::TBitmap;
: ConvertImage(bitmap, i, 0);
: delete bitmap;
: }
:
: Label2->Caption = TimeToStr(Time());
: }
: //---------------------------------------------------------------------------
: ImpThread *thread[THREAD_COUNT];
: HANDLE handle[THREAD_COUNT];
:
: void __fastcall TForm1::Button2Click(TObject *Sender)
: {
: DWORD dwWaitResult;
:
: Label3->Caption = TimeToStr(Time());
:
: index = 0;
: int i, k;
: unsigned a;
: for (i = 0; i < THREAD_COUNT; i++) {
: thread[i] = new ImpThread(i);
: a = thread[i]->Handle;
: handle[i] = &a;
: }
: Sleep(10);
:
: dwWaitResult = WaitForMultipleObjects(THREAD_COUNT, handle, TRUE, INFINITE);
:
: if (WAIT_OBJECT_0 + THREAD_COUNT - 1 == dwWaitResult) {
: Label4->Caption = TimeToStr(Time());
: }
: else {
: //Label4->Caption = "fail"; //<--------이쪽으로 들어옵니다. 왜 그럴까요?????
: Label4->Caption = TimeToStr(Time());
: }
: }
: //---------------------------------------------------------------------------
: //CreateSuspended 인자를 false로 하면 생성 즉시 시작하게 된다.
: //일반적인 Thread는 ture를 가지며 생성 하지만 실행되지 않는다.
: __fastcall ImpThread::ImpThread(int index)
: : TThread(false)
: {
: Priority = tpTimeCritical;
: Index = index;
: defaultDir = "C:\\Temp_Image\\";
: }
: //---------------------------------------------------------------------------
:
: void __fastcall ImpThread::Execute()
: {
: //EnterCriticalSection(&crit);
:
: Graphics::TBitmap* bitmap = NULL;
: bitmap = new Graphics::TBitmap;
: int index = Index + 1;
:
: AnsiString filename = defaultDir + index;
: filename += ".jpg";
: TJPEGImage *pJpeg = new TJPEGImage();
: pJpeg->LoadFromFile(filename);
:
: bitmap->Assign(pJpeg);
:
: Byte* ptr;
: unsigned char pBuffR;
: unsigned char pBuffG;
: unsigned char pBuffB;
:
: for (int y = 0; y < bitmap->Height; y++) {
: ptr = (Byte *)bitmap->ScanLine[y];
: for (int x = 0; x < bitmap->Width; x++) {
: pBuffB = ptr[3*x];
: pBuffG = ptr[3*x+1];
: pBuffR = ptr[3*x+2];
:
: ptr[3*x] = 255 - pBuffB;
: ptr[3*x+1] = 255 - pBuffG;
: ptr[3*x+2] = 255 - pBuffR;
: }
: }
:
: pJpeg->Assign(bitmap);
:
: filename = defaultDir;
: filename += "thread\\";
: filename += index;
: filename += "_r.jpg";
:
: pJpeg->SaveToFile(filename);
:
: delete pJpeg;
: delete bitmap;
:
: //LeaveCriticalSection(&crit);
: }
: //---------------------------------------------------------------------------