Thread Control and WaitCommEvent()
-
I'm currently working on a project for college where we (our project group) attach a unit we built to the serial port and interact with it using software. Everything works great... to a point... We call WaitCommEvent() which sets our thread (we created) in a block state and when a character is sent (from our hardware unit through the serial port), the software processes it properly... HOWEVER.... my problem is that... The ONLY thing that breaks the WaitCommEvent() is hardware interaction.... The main program (that spawns the thread running the WaitCommEvent) cannot kill the thread or somehow interrupt the wait event. I'm only an amateur at this, and have gotten this far by getting lost in the MSDN libraries... but I'm stumped on this one... Does anyone know any little tricks I can do or any way I can modify my code so I can lift the WaitCommEvent() suspend state using software interaction. Then allowing me to terminate the thread? :confused: lead2gold
-
I'm currently working on a project for college where we (our project group) attach a unit we built to the serial port and interact with it using software. Everything works great... to a point... We call WaitCommEvent() which sets our thread (we created) in a block state and when a character is sent (from our hardware unit through the serial port), the software processes it properly... HOWEVER.... my problem is that... The ONLY thing that breaks the WaitCommEvent() is hardware interaction.... The main program (that spawns the thread running the WaitCommEvent) cannot kill the thread or somehow interrupt the wait event. I'm only an amateur at this, and have gotten this far by getting lost in the MSDN libraries... but I'm stumped on this one... Does anyone know any little tricks I can do or any way I can modify my code so I can lift the WaitCommEvent() suspend state using software interaction. Then allowing me to terminate the thread? :confused: lead2gold
I would stay away from WaitCommEvent myself. In the past I have always configured my comm port such that when you do a WriteFile() it returns after all output characters have actually been sent and the receive returns immediately regards on whether any characters were read or not - you can then check the number of characters received. I do this in a loop with regular Sleep()s in it and a while (!bKillYourself) flag which can be set externally. Somthing like this: (A quick hack of one of my projects)
DWORD dwNumBytesRead; DWORD dwNumBytesWritten; SECURITY\_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY\_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; // use default descriptor sa.bInheritHandle = true; // allow sub-threads to inherit handle // OPEN SERIAL PORT FOR COMMUNICATION m\_hSerialPortHandle = CreateFile((LPCTSTR)m\_csCommPortName, GENERIC\_READ | GENERIC\_WRITE, 0, &sa, // needed for inherit OPEN\_EXISTING, 0, 0); if (m\_hSerialPortHandle != INVALID\_HANDLE\_VALUE) { m\_bOpen = true; if (!GetCommState(m\_hSerialPortHandle, &m\_DCB)) { text = "Serial port DCB failure."; ::SendMessage(m\_hwndParent, UWM\_UC\_STATUS, (LONG)(LPCTSTR)text, 0); } else { // make sure we are using the correct settings m\_DCB.BaudRate = CBR\_9600; // 9600 baud m\_DCB.ByteSize = 8; // 8 data bits m\_DCB.Parity = NOPARITY; // no parity m\_DCB.fParity = false; // parity checking off m\_DCB.StopBits = ONESTOPBIT; // 1 stop bit m\_DCB.fDtrControl = DTR\_CONTROL\_DISABLE; // no DTR input flow control m\_DCB.fOutxCtsFlow = false; // don't monitor CTS m\_DCB.fDsrSensitivity = false; // always read bytes received m\_DCB.fTXContinueOnXoff = true; // don't wait for XONN / XOFF m\_DCB.fOutX = false; // No XON / XOFF control m\_DCB.fRtsControl = RTS\_CONTROL\_DISABLE; // don't use RTS comms control m\_DCB.fAbortOnError = false; // don't quit on error // now apply the correct comm state to the device if (!SetCommState(m\_hSerialPortHandle, &m\_DCB)) { text = "Serial port set com status failure."; ::SendMessage(m\_hwndParent, UWM\_UC\_STATUS, (LONG)(LPCTSTR)text, 0); } // set the communication event flags if (!SetCommMask(m\_hSerialPortHandle, EV\_RXCHAR)) { text = "Serial port set com mask failure."; ::SendMessage(m\_hwndParent, UWM\_UC\_STATUS, (LONG)(LPCTSTR)text, 0); } COMMTIMEOUTS timeouts; // return immediately on reads //
-
I would stay away from WaitCommEvent myself. In the past I have always configured my comm port such that when you do a WriteFile() it returns after all output characters have actually been sent and the receive returns immediately regards on whether any characters were read or not - you can then check the number of characters received. I do this in a loop with regular Sleep()s in it and a while (!bKillYourself) flag which can be set externally. Somthing like this: (A quick hack of one of my projects)
DWORD dwNumBytesRead; DWORD dwNumBytesWritten; SECURITY\_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY\_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; // use default descriptor sa.bInheritHandle = true; // allow sub-threads to inherit handle // OPEN SERIAL PORT FOR COMMUNICATION m\_hSerialPortHandle = CreateFile((LPCTSTR)m\_csCommPortName, GENERIC\_READ | GENERIC\_WRITE, 0, &sa, // needed for inherit OPEN\_EXISTING, 0, 0); if (m\_hSerialPortHandle != INVALID\_HANDLE\_VALUE) { m\_bOpen = true; if (!GetCommState(m\_hSerialPortHandle, &m\_DCB)) { text = "Serial port DCB failure."; ::SendMessage(m\_hwndParent, UWM\_UC\_STATUS, (LONG)(LPCTSTR)text, 0); } else { // make sure we are using the correct settings m\_DCB.BaudRate = CBR\_9600; // 9600 baud m\_DCB.ByteSize = 8; // 8 data bits m\_DCB.Parity = NOPARITY; // no parity m\_DCB.fParity = false; // parity checking off m\_DCB.StopBits = ONESTOPBIT; // 1 stop bit m\_DCB.fDtrControl = DTR\_CONTROL\_DISABLE; // no DTR input flow control m\_DCB.fOutxCtsFlow = false; // don't monitor CTS m\_DCB.fDsrSensitivity = false; // always read bytes received m\_DCB.fTXContinueOnXoff = true; // don't wait for XONN / XOFF m\_DCB.fOutX = false; // No XON / XOFF control m\_DCB.fRtsControl = RTS\_CONTROL\_DISABLE; // don't use RTS comms control m\_DCB.fAbortOnError = false; // don't quit on error // now apply the correct comm state to the device if (!SetCommState(m\_hSerialPortHandle, &m\_DCB)) { text = "Serial port set com status failure."; ::SendMessage(m\_hwndParent, UWM\_UC\_STATUS, (LONG)(LPCTSTR)text, 0); } // set the communication event flags if (!SetCommMask(m\_hSerialPortHandle, EV\_RXCHAR)) { text = "Serial port set com mask failure."; ::SendMessage(m\_hwndParent, UWM\_UC\_STATUS, (LONG)(LPCTSTR)text, 0); } COMMTIMEOUTS timeouts; // return immediately on reads //
Thanks! I will try that immediately and post my success (hopefully) ... The hardware unit we built is kinda dumb, it can only send characters not read (thus I won't be using the write function)... but i will take what you've posted and see if i can play with it to make it work for me. Once again, thanks alot!:) lead2gold
-
I'm currently working on a project for college where we (our project group) attach a unit we built to the serial port and interact with it using software. Everything works great... to a point... We call WaitCommEvent() which sets our thread (we created) in a block state and when a character is sent (from our hardware unit through the serial port), the software processes it properly... HOWEVER.... my problem is that... The ONLY thing that breaks the WaitCommEvent() is hardware interaction.... The main program (that spawns the thread running the WaitCommEvent) cannot kill the thread or somehow interrupt the wait event. I'm only an amateur at this, and have gotten this far by getting lost in the MSDN libraries... but I'm stumped on this one... Does anyone know any little tricks I can do or any way I can modify my code so I can lift the WaitCommEvent() suspend state using software interaction. Then allowing me to terminate the thread? :confused: lead2gold
Like almost any file IO in Win32 WaitCommEvent() supports overlapped IO. This means that your call to executed asynchronously by the IOManager in background. You receive the results via the OVERLAPPED structure passed as last parameter. Overlapped IO is discussed in detail in MSDN. -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )
-
Like almost any file IO in Win32 WaitCommEvent() supports overlapped IO. This means that your call to executed asynchronously by the IOManager in background. You receive the results via the OVERLAPPED structure passed as last parameter. Overlapped IO is discussed in detail in MSDN. -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )
Yea, we tried that, I have no idea how Overlapped works even with the MSDN libraries. (we used them to get as far as we did) it seems as though if WaitCommEvent() is spawned (with it's parameters existing within a class) and then ComSetEvent() is executed from another thread with it's parameters existing fromt he same class, it is suspended until WaitCommEvent is complete. Is this true? lead2gold
-
Yea, we tried that, I have no idea how Overlapped works even with the MSDN libraries. (we used them to get as far as we did) it seems as though if WaitCommEvent() is spawned (with it's parameters existing within a class) and then ComSetEvent() is executed from another thread with it's parameters existing fromt he same class, it is suspended until WaitCommEvent is complete. Is this true? lead2gold
Aehm, more or less. Overlapped IO is a feature of the NT Executive (Kernel) and the Win32 API and not related to any classes. The IO Manager (a component of the Executive) executes IO request always asynchronously - if you don't use overlapped IO the calling thread is just blocked until the IO is completed. (In other words: Inside the kernel non-overlapped IO is simulated by using overlapped IO) However, I am sure you that much interested in the technical details, but want to know how to use it :-D Overlapped IO is not difficult in general, but a lot of details have to be taken into account. If the information provided by MSDN is not enough, I'd recommend to buy a good book about Windows NT system programming, like Win32 System Programming by Johnson M. Hart. (Note: I haven't read it, but people told me that it's a quite good book). Hope that helps! -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )
-
Aehm, more or less. Overlapped IO is a feature of the NT Executive (Kernel) and the Win32 API and not related to any classes. The IO Manager (a component of the Executive) executes IO request always asynchronously - if you don't use overlapped IO the calling thread is just blocked until the IO is completed. (In other words: Inside the kernel non-overlapped IO is simulated by using overlapped IO) However, I am sure you that much interested in the technical details, but want to know how to use it :-D Overlapped IO is not difficult in general, but a lot of details have to be taken into account. If the information provided by MSDN is not enough, I'd recommend to buy a good book about Windows NT system programming, like Win32 System Programming by Johnson M. Hart. (Note: I haven't read it, but people told me that it's a quite good book). Hope that helps! -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )