환경: C++ Builder XE5
화면과 파일에 Log을 기록하는 LogThread를 운영중입니다.
잘 동작하는데, 프로그램 종료할 때 문제가 생기네요.
로그를 기록하는 것이 스레드로 빠져있으니
로그를 써야할 상황인데, MainForm이 먼저 종료되면서
로그가 기록되지 않는 증상이 발생하는데요..
Form의 CloseQuery / Close 이벤트에서
Socket을 닫거나 Serial Port를 닫으면서 해당 컴포넌트의 Close 이벤트가 다시 발생하고,
이 이벤트에 대한 로그를 로그 스레드에서 처리하는데, 벌써 메인 폼은 없어져서
로그를 처리할 수 없는 상황이 생깁니다. 그냥 Sleep()으로 기다려도 MainThread가 Sleep()으로
빠져버리니 이것도 해결책이 되지 않더군요.
요지는 CloseQuery / Close 이벤트에서 LogThread가 자신의 로그 내용을 다 적을 때까지
기다려야 할 때 어떻게 하는 지..?
//---------------------------------------------------------------------------
// Close 관련 Event
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TFormMain::FormCloseQuery(TObject *Sender, bool &CanClose)
{
LogMessage("Software is closeing.....................................");
// Socket Release
ASocket->Active = false; // Disconnect event 발생 => Log 기록
BSocket->Active = false; // Disconnect event 발생 => Log 기록
// Serial Port Release
SerialPort1->Open = false; // Close Event 발생 => Log 기록
SerialPort2->Open = false; // Close Event 발생 => Log 기록
// Timer Stop
// ....
// Other Resource Release
// ....
// Message pumping
//for ( int i = 0 ; i < 10 ; i++ ) {
// Application->ProcessMessages();
//}
CanClose = true;
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::FormClose(TObject *Sender, TCloseAction &Action)
{
// Resource Release
delete pGLogSection;
delete GLogQueue;
delete GLogEvent;
Action = caFree;
return;
}
//---------------------------------------------------------------------------
// Log Thread Process
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TLogThread::Execute()
{
TWaitResult Result;
STLogMessage *pLogMessage;
while ( FormMain->m_bLogThread ) {
Result = GLogEvent->WaitFor(EVENT_WAIT_TIME); // wait 1 second
if ( Result == wrSignaled || Result == wrTimeout ) {
while ( GLogQueue->Count() ) {
pGLogSection->Enter();
pLogMessage = (STLogMessage *) GLogQueue->Pop();
pGLogSection->Leave();
LogWrite(pLogMessage);
delete pLogMessage;
}
} else if ( Result == wrAbandoned ) { // Event Object was destored
// wrError: An error occured while waiting.
// Check the LastError property for an error
// code giving more informaiton.
} else {
// nothing to do..
}
//G_pSoundEvent->ResetEvent(); // Auto Event Reset mode
}
}
//---------------------------------------------------------------------------
void TLogThread::LogWrite(STLogMessage *pLogMessage)
{
if ( FormMain->Memo->Lines->Count > 100 ) FormMain->Memo->Lines->Clear();
TDateTime t = pLogMessage->LogTime;
USHORT iHour, iMinute, iSec, iMSec;
t.DecodeTime(&iHour, &iMinute, &iSec, &iMSec);
UnicodeString sLogMsg;
sLogMsg = sLogMsg.sprintf(L"[%02d:%02d:%02d] ",iHour, iMinute, iSec);
sLogMsg += pLogMessage->LogMessage;
FormMain->Memo->Lines->Insert(0, sLogMsg); // 메인 폼의 로그창에 기록
if ( pLogMessage->bFile ) {
m_Log.LogMessage(sLogMsg); // 로그 파일에 기록
}
}
|