Re: Reading Serial Port
"clinisbut" <clinisbut@gmail.com> wrote in message
news:aae33d0b-121c-469e-8477-13df4e695c4d@e25g2000prg.googlegroups.com...
Ok, finally I think I solved it...
I added a
delete pMySerial;
After WFSO in OnDestroy so I have no memory leaks now! Thank you.
About pReaderThread, I didn't set its m_bAutoDelete to FALSE, so I
suppose that I just need to WFSO for its m_hThread, isn't it?
Good...yes, just wait for WFSO to know the thread is gone.
This is my updated code with some comments:
First, creating the object:
(MySerial*) pMySerial = (MySerial*)
AfxBeginThread( RUNTIME_CLASS( MySerial ), THREAD_PRIORITY_NORMAL, 0,
CREATE_SUSPENDED );
That's ok. Then I call:
pMySerial->ResumeThread();
pMySerial->openPort( port_number );
Umm, you don't set pMySerial->m_bAutoDelete = FALSE!
Here is my class (serial port related code ommited)
//Open_port(), here I crete the pReaderThread, a worker thread that
reads serial port
BOOL MySerial::openPort( int port )
{
opened = TRUE;
ShutdownEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
pReaderThread = AfxBeginThread( ReaderThread, this,
THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED );
//pReaderThread->m_bAutoDelete = FALSE;
//pReaderThread->ResumeThread();
return TRUE;
}
Uncomment pReaderThread->ResumeThread()
//This is the famous ReaderThread, a worker thread that exits when
ShutDownEvent is signaled
UINT ReaderThread( LPVOID cT )
{
MySerial* SerialHandler = (MySerial*)cT;
HANDLE waiters[2];
waiters[0] = SerialHandler->ShutdownEvent;
waiters[1] = SerialHandler->ovReader.hEvent;
while( reading )
{
unsigned char buffer[MAX_BUFFER_SIZE];
BOOL ok = ::ReadFile( SerialHandler->hComm, buffer, MAX_BUFFER_SIZE
-1, &bytesRead, &SerialHandler->ovReader );
if( !ok )
{
//Some code...
DWORD result = ::WaitForMultipleObjects( 2, waiters, FALSE,
INFINITE );
switch( result )
{
case WAIT_OBJECT_0: //Event shutdown
reading = FALSE; //Here loop
quits
continue;
//More code
}
}
//More code to read
}
TRACE("\nREADER THREAD STOPPED.\n");
return 0;
}
//And finally, the closePort()
void MySerial::closePort( WPARAM wparam, LPARAM lparam)
{
TRACE("Hi!");
if( opened )
{
SetEvent( ShutdownEvent );
TRACE("closing pReaderThread.\n");
WaitForSingleObject( pReaderThread->m_hThread, INFINITE );
//If I set in openPort() pReader->Thread->m_bAutodelete = FALSE...
// CloseHandle( pReaderThread->m_hThread ); //...Here I've
got an Exception error
The reason is pReaderThread object has been deleted, so you can't
dereference pReaderThread->m_hThread. You would need to copy this in the
beginning to another HTHREAD variable and use it instead.
// delete pReaderThread; //
BOOL ok = PurgeComm( hComm, PURGE_RXABORT|PURGE_RXCLEAR );
::CloseHandle( WriteEvent );
::CloseHandle( ShutdownEvent );
::CloseHandle( ReadEvent );
::CloseHandle( hComm );
PostQuitMessage(0);
//PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0);
opened = FALSE;
TRACE("THREAD STOPPED\n");
}
else
{
TRACE("Not opened.");
PostQuitMessage(0);
//PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0);
}
}
And in my OnDestroy I do this:
void CUart3DEMODlg::OnDestroy()
{
CDialog::OnDestroy();
TRACE("closing port.\n");
if( serial_created ) //<<---Note this flag
{
TRACE("We have to kill pMySerial.\n");
pMySerial->ResumeThread();
pMySerial->PostThreadMessage( WM_MYSERIAL_CLOSE, 0, 0 );
WaitForSingleObject( pMySerial->m_hThread, INFINITE );
delete pMySerial;
TRACE("Port closed.\n");
}
}
Why do you have to call pMySerial->ResumeThread() when it is not suspended?
I don't see why you need to set m_bAutoDelete = TRUE for either pMySerial or
pReaderThread since you don't access any data members from them after the
threads have stopped.
I have to thank all people that helped me to find the solution,
But... one last thing (sorry):
The flag serial_created is true when I create pMySerial. When
serial_created is true at the moment of exit App, I must close it
properly.
But you'll agree with me that's shoddy... Is there a better way to
detect that pMySerial exists??
Can't you check if pMySerial is NULL?
-- David