C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[68562] Re:Re:Re: VCL 프레임웍 구조 때문 입니다...
빌더(TWx) [builder] 1674 읽음    2012-11-19 13:10
: aa 님이 쓰신 글 :
: : 스레드 문제 아니면 소스코드나 TClientSocket에 버그가 있는게 아닐까요?
: :
: :
: : zzang9un 님이 쓰신 글 :
: : : 요즘 버전에선 거의 안쓰지만...
: : : 예전 소스에 자주 사용했던 TClientSocket을 사용하다보니
: : : 이상한 현상을 발견해서 질문 드립니다.
: : :
: : : Client 소켓 2개를 사용해서 별도로
: : : Communication이라는 클래스를 만들었습니다.
: : : 여기에는 TClientSocket이 2개 들어있죠...
: : :
: : : 그런데....
: : : MainForm에서 Communication 클래스를 직접 생성해서
: : : 소켓의 Host, Port를 설정하고 Active를 true로 변경하면
: : : Active 값도 변경이 잘 되고 Server 접속이 잘 되는데....
: : :
: : : MainForm에서 별도 생성한 Thread에서
: : : Communication 클래스를 생성해서 똑같이 설정하고
: : : Active를 true로 변경하면 Active 변경이 true안되고 접속도 안됩니다.
: : :
: : : Communication 클래스는 동일한 것을 사용했으니...
: : : 차이라면... MainForm에서 생성한 경우와 Thread에서 생성한 경우인데...
: : : 어떤 문제가 있는 건지 잘 모르겠습니다...
: : :
: : : TClientSocket이 Thread 기반으로 되어 있다고 얼핏 들은 것 같습니다...
: : : 그렇더라도 다른 Thread에서 돌아가는 게 문제가 있나요??
: : : 왜 MainForm에서는 잘되는데 Thread에서는 안될까요?
: : : (Thread에서 Thread 생성하는 게 문제가 있는건지도 궁금하네요.. )



답변)


TServerSocket 이 Accept 되는 클라이언트 소켓을 처리하기 위해 쓰레드를 생성해서 사용하지만...

TClientSocket 자체는 쓰레드를 사용하지 않습니다. 대신 Hidden 윈도우즈를 하나 생성해서 메세지 기반으로...

동작하는 구조로 되어 있고... FD_CONNECT, FD_CLOSE, FD_READ, FD_WRITE 등의... 관련 이벤트가 발생하면...

생성된 쓰레드의 Message Queue에... Windows Socket Layer 에서 Windows Message 를 보내게 됩니다...

그러나 VCL 프레임웍은 Windows Message를 처리하기 위한 Message Dispatch 로직을... 애플리케이션 메인 UI 쓰레드..

하나에서만 처리하도록 되어있기 때문에... 생성된 쓰레드의 Message Queue 를 Dispatch 하지 못하게 됩니다...

쓰레드 객체는... OS에 의해서 고유한 Thread Message Queue를 갖게 됩니다...


비슷한 경우로... TTimer를 예로 들어보죠...

TTimer 역시... Hidden 윈도우를 생성해서 클래스 자체에서 WM_TIMER 메세지를 처리하도록 구현되어 있는데...

별도의 쓰레드에 의해서 생성되면... Single UI Thread 구조로 설계되어 있는 VCL 프레임웍의 구조적인 한계 때문에...

WM_TIMER 메세지가 생성된 쓰레드로 Dispatch 되지 못합니다...


bool bQuit = false;

class TMyThread : public TThread
{
public:
	void __fastcall Execute()
	{
		timer = new TTimer(NULL);
		timer->Interval = 1000;
		timer->OnTimer = TimerHandler;
		timer->Enabled = true;

		while(!bQuit)
		{
			Sleep(10);
		}
		delete timer;
	}
private:
	TTimer *timer;
	void __fastcall TimerHandler(System::TObject* Sender)
	{
		static int i = 0;
		String s;
		s.printf(L"timer %d", i++);
		OutputDebugStringW(s.c_str());
	}
};

TMyThread *myThread;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	myThread = new TMyThread();
}
__fastcall TForm1::~TForm1()
{
	bQuit = true;
	myThread->WaitFor();
	delete myThread;
}


위와 같이 TTimer 가 별도의 쓰레드에 의해서 생성될 경우... 쓰레드 자체는 실행이 될지라도, 윈도우즈 메시지가...

Dispatch 되지 않기 때문에... 제대로 동작하지 않게 됩니다... 윈도우즈 메세지가 정상적으로 Dispatch 되도록 하려면...

생성된 쓰레드 자체에서 아래와 같은 식으로 Message Dispatch 로직을 갖고 있어야 합니다...


bool bQuit = false;

class TMyThread : public TThread
{
public:
	void __fastcall Execute()
	{
		timer = new TTimer(NULL);
		timer->Interval = 1000;
		timer->OnTimer = TimerHandler;
		timer->Enabled = true;

		MSG msg;
		BOOL bRet;

		while( !bQuit)
		{
			bRet = PeekMessage( &msg, NULL, 0, 0, PM_REMOVE);

			if( bRet == true)
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}

		delete timer;
	}

private:
	TTimer *timer;
	void __fastcall TimerHandler(System::TObject* Sender)
	{
		static int i = 0;
		String s;
		s.printf(L"timer %d", i++);
		OutputDebugStringW(s.c_str());
	}
};

TMyThread *myThread;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	myThread = new TMyThread();
}
__fastcall TForm1::~TForm1()
{
	bQuit = true;
	myThread->WaitFor();
	delete myThread;
}



위와 같이 쓰레드에서 Message Dispatch 로직을 갖고 있어야 합니다...


Visual Studio 에서 MFC의 경우에는...  CWinThread 라는 클래스가 있는데...

CCmdTarget > CWinThread 상속 관계로 구현되어 있어서... CWinThread 클래스 자체가...

Worker Thread의 역할로 사용될 수도 있고, UI Thread로도 사용될 수 있는 구조로 구현되어 있습니다...

Message Dispatch도 쓰레드 마다 동작하도록 되어 있다는 거죠...


그러나 VCL 프레임웍은...

프레임웍 전체 구조가 싱글 쓰레드로 구현되어 있고... Message Dispatch 도 마찬가지로... 메인 UI 쓰레드 하나가 처리하는...

구조적 한계를 갖기 때문에... 위와 같이 Message Dispatch 로직을... 사용자가 일일히 코딩해 줘야 합니다...



...

+ -

관련 글 리스트
68557 TClientSocket Active 관련 질문드립니다. zzang9un 1516 2012/11/18
68558     Re: 스레드 문제 아닐까요? aa 1271 2012/11/18
68560         Re:Re: 스레드 문제 아닐까요? 장성호 1425 2012/11/19
68562             Re:Re:Re: VCL 프레임웍 구조 때문 입니다... 빌더(TWx) 1674 2012/11/19
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.