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
[44244] Re:Re:Re:답변 고맙습니다. 근데요..
넘초보 [mspower] 1479 읽음    2006-03-24 08:33
Synchronize 는 빌더쓰레드(TThread) 의 메소드 입니다.

쓰레드를 자동 생성하셨다면 헤더에 파일이 인클루드되었을텐데요.

없다면 <Classes.hpp> 이 파일을 인클루드 하시고요.


그리고, 제가 드린 답변중에

void __fastcall TfMain::WLog()  <--- 요기서 TfMain 에 아니라 해당 쓰레드 클래스네요.
{
         if(fMain->reLog->Lines->Count > 1000) fMain->reLog->Clear();
         fMain->reLog->SelStart = 0;
         fMain->reLog->SelAttributes->Color = Color;
         fMain->reLog->Lines->Insert(0, m_sMemo); // 멤버변수에 저장된 내용.
}

Synchronize() 메소드는 인자와 리턴값이 없는 함수를 원하기 때문에,

임시로 쓰레드의 멤버변수에 저장을 하고,

이를 처리하는 메소드에서 알수 있도록 하려는 것입니다.

좋은 하루 되세요..^^


% 로그를 실제 서비스 프로그램에 사용하며 알게 된 것은

님처럼 각각의 쓰레드(많은 양의 로그를 찍는)에서 화면출력을 한다면

각 쓰레드간의 동기화로 인해 대기시간이 길어진다는 겁니다.

모든 쓰레드가 화면 출력시간에 맞추어 진다는 거죠.

파일로 찍을때도 마찬가지고요.

전 이를 해결하기 위해 중간에 관리자를 두고, 파일의 경우 일정량, 일정시간동안

모은후 한꺼번에 저장하고, 화면은 사용자의 요구가 있을경우에 출력하도록 하고

있습니다.







하니 님이 쓰신 글 :
: 답변에 감사 드립니다.
:
: 근데 에러가 나거든요??
: E2268 Call to undefined function 'Synchronize' 라고 에러가 납니다.
: 그리고 한가지 궁금한것 .. 
: fMain은 메인 폼이고  메인폼 또는 다른 폼에서 여러개의 스레드를 생성하는데
: fMain의 멤버 변수에 저장하면 다른 스레드가 접근해서 데이타를 바꿀수 있을 거 같은데요..
: 그럼 원하는 로그값이 아니라 다른 로그값이 출력될 수도 있을 거 같은데요..
: 다시한번 답변 부탁드립니다.
:
:
:
:
: 넘초보 님이 쓰신 글 :
: : if(fMain->reLog->Lines->Count > 1000) fMain->reLog->Clear();
: :         fMain->reLog->SelStart = 0;
: :         fMain->reLog->SelAttributes->Color = Color;
: :         fMain->reLog->Lines->Insert(0,sMemo);
: :
: : 위 부분에 Synchronize 를 적용하면 되겠네요.
: :
: : sMemo = sDateTime+" "+sMemo;
: : m_sMemo = sMemo; // 멤버변수에 갖고 있자.
: : Synchronize(WLog)
: :
: : void __fastcall TfMain::WLog()
: : {
: :         if(fMain->reLog->Lines->Count > 1000) fMain->reLog->Clear();
: :         fMain->reLog->SelStart = 0;
: :         fMain->reLog->SelAttributes->Color = Color;
: :         fMain->reLog->Lines->Insert(0, m_sMemo); // 멤버변수에 저장된 내용.
: : }
: :
: :
: :
: :
: : hann1004 님이 쓰신 글 :
: : : 제가 지금 만들고 있는 프로그램이 멀티 스레드 프로그램인데요..
: : : 100개이상의 스레드를 한꺼번에 실행시키거든요??
: : : 근데 메인폼에 스레드의 로그를 표출하기 위해 richedit 박스를 올려놓고 스레드 생성시 또는 이벤트 발생시 richedit박스에 표출해주고 있는데...
: : : 테스트용으로 1개의 스레드를 가지고 테스트 했을 때는 전혀 문제가 없거든요??
: : : 근데 여러개를 띠웠을때는
: : : Project COMM.exe raised exeption class EOutOfResources with message 'RichEdit Line Insertion error' 라고 발생하네요.....
: : : 표출해주는 함수에 인자가 있어서 synchronize를 사용하면 될거 같은데... 함수에 인자가 있어서 불가능할거 같구..
: : : 혹시 경험해 보신분이나 잘 알고 계신 고수분들 도움 요청드립니다.
: : : 참고로 os는 2000 인데요... 2003 서버에서 사용할거구요..
: : : 소스는 길어서 전체를 올릴수 없는데..
: : : 스레드 생성하는 부분과 로그 함수를 올립니다.
: : : 고수분들 도와 주십시요
: : :
: : : ///////////////스레드에서 다른 스레드 생성하는 부분////////////////////
: : :     fMain->WriteLog(Global->m_WinName,"TPipeCreateThread.cpp","Execute",m_sThreadInfo+"TPipeCreateThread-이벤트 ",ELSE);
: : :
: : :     FreeOnTerminate = true;
: : :     //---- Place thread code here ----
: : :     while(!Terminated){
: : :         switch(m_nDivision){
: : :             case SERVER_CREATE: //Write Read용으로 Instance를 2개 실행시킴.
: : :                                 //WaitForSingleObject(m_hCreateEvent,INFINITE);
: : :                     fMain->WriteLog(Global->m_WinName,"TPipeCreateThread.cpp","Execute",m_sThreadInfo+"TPipeCreateThread-서버용 파이프",NORMAL);
: : :                     dwReturn = WaitForMultipleObjects(2,a_hEvents,false,INFINITE);
: : :                     dwEvent = dwReturn - WAIT_OBJECT_0;
: : :                     if(dwEvent == 0){
: : :                                 fMain->WriteLog(Global->m_WinName,"TPipeCreateThread.cpp","Execute",m_sThreadInfo+"TPipeCreateThread-파이프 생성",ELSE);
: : :                                 a_hPipe=CreateNamedPipe(m_sPipeName.c_str(),
: : :                                                         PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE,//PIPE_TYPE_BYTE,
: : :                                                         2,MAX_PIPE_DATA_SIZE,MAX_PIPE_DATA_SIZE,10000,NULL);
: : :                                 a_bCon=ConnectNamedPipe(a_hPipe,NULL);
: : :                                 if((a_bCon==false) && (GetLastError() == ERROR_PIPE_CONNECTED)) a_bCon=true;
: : :                                 if(a_bCon==true){
: : :                                     Sleep(10);
: : :                                     fMain->WriteLog(Global->m_WinName,"TPipeCreateThread.cpp","Execute",m_sThreadInfo+"TPipeCreateThread-파이프상태체크",ELSE);
: : :                                     GetNamedPipeHandleState(a_hPipe,NULL,&(a_pPipeInfo->dwInstance),NULL,NULL,NULL,0);
: : :                                     a_pPipeInfo->hPipe = a_hPipe;
: : :                                     a_pPipeInfo->nDivision = SERVER_CREATE_PIPE;
: : :                                     a_pPipeInfo->nVMS = m_nVMS;
: : :                                     fMain->WriteLog(Global->m_WinName,"TPipeCreateThread.cpp","Execute",m_sThreadInfo+"TPipeCreateThread-포스트메시지 전송",DETAIL);
: : :                                     PostMessage(m_hWnd,UM_PIPE_CONNECTION_SUCCESS,(WPARAM)a_hPipe,(LPARAM)a_pPipeInfo);
: : :                                 }
: : :                                 else CloseHandle(a_hPipe);
: : :                     }
: : :                     break;
: : :             case CLIENT_CONNECTION:
: : :                     fMain->WriteLog(Global->m_WinName,"TPipeCreateThread.cpp","Execute",m_sThreadInfo+"TPipeCreateThread-클라이언트용파이프",ELSE);
: : :                                 //WaitForSingleObject(m_hCreateEvent,INFINITE);
: : :                     dwReturn = WaitForMultipleObjects(2,a_hEvents,false,INFINITE);
: : :                     fMain->WriteLog(Global->m_WinName,"TPipeCreateThread.cpp","Execute",m_sThreadInfo+"TPipeCreateThread-파이프 생성",ELSE);
: : :                     dwEvent = dwReturn - WAIT_OBJECT_0;
: : :                     if(dwEvent == 0){
: : :                                 do{
: : :                                     a_bCon=WaitNamedPipe(m_sPipeName.c_str(),10000);
: : :                                     if(a_bCon){
: : :                                         a_hPipe=CreateFile(m_sPipeName.c_str(),GENERIC_READ | GENERIC_WRITE,
: : :                                                            0,NULL,OPEN_EXISTING,0,NULL);
: : :                                         if(a_hPipe!=INVALID_HANDLE_VALUE){
: : :                                             fMain->WriteLog(Global->m_WinName,"TPipeCreateThread.cpp","Execute",m_sThreadInfo+"TPipeCreateThread-파이프 상태체크",ELSE);
: : :                                             GetNamedPipeHandleState(a_hPipe,NULL,&(a_pPipeInfo->dwInstance),NULL,NULL,NULL,0);
: : :                                             a_pPipeInfo->hPipe = a_hPipe;
: : :                                             a_pPipeInfo->nDivision = CLIENT_CONNECTION_PIPE;
: : :                                             a_pPipeInfo->nVMS = m_nVMS;
: : :                                             fMain->WriteLog(Global->m_WinName,"TPipeCreateThread.cpp","Execute",m_sThreadInfo+"TPipeCreateThread- 포스트메시지 전송",DETAIL);
: : :                                             PostMessage(m_hWnd,UM_PIPE_CONNECTION_SUCCESS,(WPARAM)a_hPipe,(LPARAM)a_pPipeInfo);
: : :                                         }
: : :                                     }
: : :                                     Sleep(100);
: : :                                 }while(!a_bCon);
: : :                     }
: : :                     break;
: : :         }
: : :     }
: : :
: : :
: : : //////////////////////////////스레드 생성자///////////////////////////////////////
: : : __fastcall TPipeReadThread::TPipeReadThread(HANDLE hPipe,
: : :                                             int nVMS,
: : :                                             HANDLE hWnd,
: : :                                             HANDLE hReadEvent,
: : :                                             int nFlag)
: : :                                             : TThread(true)
: : : {
: : :     m_hPipe = hPipe;
: : :     m_nVMS = nVMS;
: : :     m_hWnd = hWnd;
: : :     m_hReadEvent = hReadEvent;
: : :     m_nFlag = nFlag;
: : :     if(m_nFlag == VMSINTERFACE) m_sEXEName = "VMSINTERFACE";
: : :     else m_sEXEName = "VMSCOMM";
: : :     m_sThreadInfo = nVMS ;//+ "-" + hPipe;
: : :     Priority = tpNormal;
: : :     fMain->WriteLog(Global->m_WinName,"TPipeReadThread.cpp","TPipeReadThread",m_sThreadInfo+"스레드 생성완료",DETAIL);
: : :     Resume();
: : :
: : :
: : : }
: : : ////////////////////////////로그작성함수////////////////////////////////////////
: : : 각각의 Level에 따라서 표출색을 달리하고 Level에 따라 파일또는 화면에 호출하는 함수입니다.
: : : 위의 두부분에 서 보시면 fMain->WriteLog라고 되어있는 부분이 모두 로그를 표출하는 부분입니다.
: : :
: : : void __fastcall TfMain::WriteLog(AnsiString sExeName, AnsiString sSource, AnsiString sFunction, AnsiString sMemo,int Level)
: : : {
: : : //표출로그
: : :
: : : try{
: : :     if(Level <= cboView->ItemIndex){
: : :         TColor Color;
: : :         switch(Level){
: : :             case ALERT :    //alert --
: : :                Color = clRed;
: : :                break;
: : :             case WARN :     //warn
: : :                Color = clBlue;
: : :                break;
: : :             case NORMAL :   //normal
: : :                Color = clFuchsia;
: : :                break;
: : :             case DETAIL :   //detail
: : :                Color = clBlack;
: : :                break;
: : :         }
: : :         String sDateTime = FormatDateTime("[YYYY/MM/DD, TT]",Now());
: : :
: : :         sMemo = sDateTime+" "+sMemo;
: : :
: : :         if(fMain->reLog->Lines->Count > 1000) fMain->reLog->Clear();
: : :         fMain->reLog->SelStart = 0;
: : :         fMain->reLog->SelAttributes->Color = Color;
: : :         fMain->reLog->Lines->Insert(0,sMemo);
: : :     }
: : : }catch(...){
: : : ;
: : : }
: : :
: : : try{
: : :     if(Level <= fMain->cboSave->ItemIndex){
: : :         if(Global->m_Options.LOG.bFileLogging){
: : :             String a_sDate = FormatDateTime("YYYYMMDD", Now());
: : :             String a_sTime = FormatDateTime("<HH:NN:SS> ", Now());
: : :             String a_sFileName, a_sTmp;
: : :             TFileStream *a_FileStream;
: : :             const WORD OPENMODE = fmOpenReadWrite | fmShareCompat | fmShareDenyNone;
: : :
: : :             a_sFileName = LOG_PATH+sExeName;
: : :             if (!DirectoryExists(a_sFileName))
: : :             {
: : :                 if (!CreateDir(a_sFileName))
: : :                     throw Exception("Cannot create \\"+sExeName);
: : :             }
: : :
: : :             a_sFileName += "\\"+a_sDate+".log";
: : :             if(!FileExists(a_sFileName)) FileClose(FileCreate(a_sFileName));
: : :             a_FileStream = new TFileStream(a_sFileName,OPENMODE);
: : :             a_FileStream->Seek(0, soFromEnd);
: : :
: : :             a_sTmp = a_sTime+sSource+"/"+sFunction+":"+sMemo;
: : :             a_FileStream->Write(a_sTmp.c_str(), a_sTmp.Length());
: : :             a_FileStream->Write("\r\n", 2);
: : :             delete a_FileStream;
: : :             a_FileStream = NULL;
: : :         }
: : :     }
: : : }catch(...)
: : : {
: : : ;
: : : }
: : : }
: : : //---------------------------------------------------------------------------

+ -

관련 글 리스트
44221 해결방법을 모르겠어요... 도와주세요..스레드 사용시 리치에디터에러 hann1004 1515 2006/03/22
44235     Re:해결방법을 모르겠어요... 도와주세요..스레드 사용시 리치에디터에러 넘초보 1959 2006/03/23
44237         Re:Re:답변 고맙습니다. 근데요.. 하니 1261 2006/03/23
44244             Re:Re:Re:답변 고맙습니다. 근데요.. 넘초보 1479 2006/03/24
44245                 Re:Re:Re:Re:답변 고맙습니다. 꾸벅 ^^ 하니 1953 2006/03/24
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.