|
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(...)
: : : {
: : : ;
: : : }
: : : }
: : : //---------------------------------------------------------------------------
|