김진호님 답변 감사드립니다.
우선 bWaitAll을 TRUE로 세팅한 것은 모든 Thread를 기다리기 위해서입니다.
우선 bWaitAll을 false로 세팅하면 생성된 Thread 중에 한개라도 signal되면 빠져 나오지 않나요?
그렇게 알고 있습니다.
저 또한 C++ Buillder 6을 사용하고 있고 이것으로 프로그램을 작성했습니다.
TThread를 상속 받은 Class를 만들어서 작성한 것으로 Thread->Handle을 HANDLE 배열(handle)에 넣어
WaitForMultipleObjects()함수를 이용 기다리게 한 것입니다.
TThread Class를 이용에 어려움이 있어서 CreateThread()함수를 이용해서 다시 테스트 프로그램을
작성해 보려고 합니다.
Web 서핑중에 찾은 자료를 보면 WaitForMultipleObjects()함수는 64개 이상의 Thread는 기다리지 못하고
failed로 간다고 하네요. 64개로 제한되어 있다고 하네요.
<<
http://cafe.naver.com/cyberzone/623>>
그래서 개수를 50개로 줄여 보았지만 그래도 fail로 리턴되는 것을 확인했습니다.
김진호.불사새 님이 쓰신 글 :
: 우선 코드가 길고...... 저에겐 빌더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);
: : }
: : //---------------------------------------------------------------------------