BlairFonville
Technical User
I have a great problem. I need to have two my program reading two serial ports at the same time. So the clear solution to to have three threads. 1 for com1, 1 for com2, and 1 for the main program. If I run my program and set it up to read only com1 the program reads the serial device beautifully (it is a GPS). If I then run my program and set it up to read only com2 the program reads the com2 device perfectly. The problem occurs only when I setup both ports and try to have the program read both at the same time.
I didn't expect to have any problems since I am instantiating each port seperately. I have verified that I get to the thread class (which I call CCommThread) twice, one time for each port. CCommControl is the class that I use to give each device its own instantiation. I setup the ports here, establish a port handle, and create and terminate the thread for the port. Here is what I am doing...
// My document class
class CPRGPSComDoc : public CDocument
{ ...
CCommControl m_ccGPSPort; //GPS CommControl
CCommControl m_ccTNCPort; //TNC CommControl
}
// My com port control class
------------------------------------------------
class CCommControl // HEADER
{ ...
CCommThread* m_pThread;
}
// Here is where I setup the ports' handles
LONG CCommControl::SetPortHandle(CString port)
{
lpszDevice = port;
m_lLastError = ERROR_SUCCESS; //Reset error state
m_hCommPort = CreateFile(lpszDevice,
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security
OPEN_EXISTING,
0, // no overlapped I/O
NULL); // null template
if (m_hCommPort == INVALID_HANDLE_VALUE)
{
m_hCommPort = 0; // Reset file handle
m_lLastError = ::GetLastError();
return m_lLastError;
}
return m_lLastError;
}
And this is where I "poll" the GPS or the TNC. Both devices have their own CCommControl instantiation (as shown above in the document class header)
void CCommControl:ollData()
{
//Create new (suspended) UI thread
m_pThread = (CCommThread*)AfxBeginThread(RUNTIME_CLASS CCommThread),
THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
//Initialize CCommThread member variables
m_pThread->m_hCommHandle = m_hCommPort;
m_pThread->m_bSelectPollMethod = m_bselectPollMethod;
m_pThread->m_GPSSentenceType = m_GPSSentenceType;
m_pThread->m_pView = m_pView; //Give it view class access
//Create a duplicate handle of the thread.
//This is so I can WM_QUIT the thread and still have
//access to its status after MFC autodeletes it. This
//allows me to have verification that it has terminated.
//Reference Programming Windows With MFC (p.994)
BOOL ret = DuplicateHandle(GetCurrentProcess(),
m_pThread->m_hThread,
GetCurrentProcess(), &m_dupThreadHandle, 0, FALSE,
DUPLICATE_SAME_ACCESS);
//Resume thread Operations
DWORD ResumeReturn = m_pThread->ResumeThread();
}
Now, this all seems to work fine (especially because it works perfectly when I only poll a single port- instead of both ports at the same time). I believe that I have narrowed the problem to within the CCommThread class
(given below)
void CCommThread::ReadPort()
{
do
{
ReceivedChar = WaitCommEvent (m_hCommHandle,&commevent,NULL);
if (ReceivedChar)
::ReadFile(m_hCommHandle, &sBuffer, 1,
&iBytesRead, NULL);
...
}
This is a short clip of the readport function. But I have determined that the program stops responding at this point. I believe it has a problem with the WaitCommEvent function.
I know that this is a long post, and I appologize. But, I am really confused at this point. I can't figure out why it isn't working. Could it have anything to do with the overlapped I/O? I don't understand what overlapped
is.
Anyway, Thanks for reading. I would really appreciate some help here.
Thanks, Blair
PS. I have a feeling that the formatting of this post will be messed up. If so, sorry about that
I didn't expect to have any problems since I am instantiating each port seperately. I have verified that I get to the thread class (which I call CCommThread) twice, one time for each port. CCommControl is the class that I use to give each device its own instantiation. I setup the ports here, establish a port handle, and create and terminate the thread for the port. Here is what I am doing...
// My document class
class CPRGPSComDoc : public CDocument
{ ...
CCommControl m_ccGPSPort; //GPS CommControl
CCommControl m_ccTNCPort; //TNC CommControl
}
// My com port control class
------------------------------------------------
class CCommControl // HEADER
{ ...
CCommThread* m_pThread;
}
// Here is where I setup the ports' handles
LONG CCommControl::SetPortHandle(CString port)
{
lpszDevice = port;
m_lLastError = ERROR_SUCCESS; //Reset error state
m_hCommPort = CreateFile(lpszDevice,
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security
OPEN_EXISTING,
0, // no overlapped I/O
NULL); // null template
if (m_hCommPort == INVALID_HANDLE_VALUE)
{
m_hCommPort = 0; // Reset file handle
m_lLastError = ::GetLastError();
return m_lLastError;
}
return m_lLastError;
}
And this is where I "poll" the GPS or the TNC. Both devices have their own CCommControl instantiation (as shown above in the document class header)
void CCommControl:ollData()
{
//Create new (suspended) UI thread
m_pThread = (CCommThread*)AfxBeginThread(RUNTIME_CLASS CCommThread),
THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
//Initialize CCommThread member variables
m_pThread->m_hCommHandle = m_hCommPort;
m_pThread->m_bSelectPollMethod = m_bselectPollMethod;
m_pThread->m_GPSSentenceType = m_GPSSentenceType;
m_pThread->m_pView = m_pView; //Give it view class access
//Create a duplicate handle of the thread.
//This is so I can WM_QUIT the thread and still have
//access to its status after MFC autodeletes it. This
//allows me to have verification that it has terminated.
//Reference Programming Windows With MFC (p.994)
BOOL ret = DuplicateHandle(GetCurrentProcess(),
m_pThread->m_hThread,
GetCurrentProcess(), &m_dupThreadHandle, 0, FALSE,
DUPLICATE_SAME_ACCESS);
//Resume thread Operations
DWORD ResumeReturn = m_pThread->ResumeThread();
}
Now, this all seems to work fine (especially because it works perfectly when I only poll a single port- instead of both ports at the same time). I believe that I have narrowed the problem to within the CCommThread class
(given below)
void CCommThread::ReadPort()
{
do
{
ReceivedChar = WaitCommEvent (m_hCommHandle,&commevent,NULL);
if (ReceivedChar)
::ReadFile(m_hCommHandle, &sBuffer, 1,
&iBytesRead, NULL);
...
}
This is a short clip of the readport function. But I have determined that the program stops responding at this point. I believe it has a problem with the WaitCommEvent function.
I know that this is a long post, and I appologize. But, I am really confused at this point. I can't figure out why it isn't working. Could it have anything to do with the overlapped I/O? I don't understand what overlapped
is.
Anyway, Thanks for reading. I would really appreciate some help here.
Thanks, Blair
PS. I have a feeling that the formatting of this post will be messed up. If so, sorry about that