SetTimer() in Serial Comm Program Question
-
Question on How SetTimer() Works: When the Timer goes off and it calls the OnTimer() function, does it wait until that function ends and the program returns to the OS before the Timer starts its countdown again or does it automatically restart the countdown once the OnTimer() function is called? My Reason for asking is this: I made a Multithreaded MFC serial communication program where the flow of data is continuous. Thus the way I have it is I use an Infinite loop of (Read data, do something with data and loopback to read more data), however this causes the cpu time to be completely used (99-100%). Now since the program is much faster then the flow of data what I want to do is: Read data, do something with it, then return to the OS then go back to the read routine and do it again so the cpu is used as minimally as possible. This is where my question comes in: How could I go about being able to recall the read function once I return to the OS. As per my first question I was thinking of using SetTimer() but I dont know if it is the best possible solution to the problem. Maybe some type of event could work, but I dont think it could be monitored if the program control is with the OS. Does anyone have any advice or answers to my 2 questions? Thanks
-
Question on How SetTimer() Works: When the Timer goes off and it calls the OnTimer() function, does it wait until that function ends and the program returns to the OS before the Timer starts its countdown again or does it automatically restart the countdown once the OnTimer() function is called? My Reason for asking is this: I made a Multithreaded MFC serial communication program where the flow of data is continuous. Thus the way I have it is I use an Infinite loop of (Read data, do something with data and loopback to read more data), however this causes the cpu time to be completely used (99-100%). Now since the program is much faster then the flow of data what I want to do is: Read data, do something with it, then return to the OS then go back to the read routine and do it again so the cpu is used as minimally as possible. This is where my question comes in: How could I go about being able to recall the read function once I return to the OS. As per my first question I was thinking of using SetTimer() but I dont know if it is the best possible solution to the problem. Maybe some type of event could work, but I dont think it could be monitored if the program control is with the OS. Does anyone have any advice or answers to my 2 questions? Thanks
A simple test - put an
AfxMessageBox()
in theOnTimer()
funtion, set the timer period to say 3 seconds, let the message box stay open for say 2 seconds. Elaine :rose: The tigress is here :-D -
Question on How SetTimer() Works: When the Timer goes off and it calls the OnTimer() function, does it wait until that function ends and the program returns to the OS before the Timer starts its countdown again or does it automatically restart the countdown once the OnTimer() function is called? My Reason for asking is this: I made a Multithreaded MFC serial communication program where the flow of data is continuous. Thus the way I have it is I use an Infinite loop of (Read data, do something with data and loopback to read more data), however this causes the cpu time to be completely used (99-100%). Now since the program is much faster then the flow of data what I want to do is: Read data, do something with it, then return to the OS then go back to the read routine and do it again so the cpu is used as minimally as possible. This is where my question comes in: How could I go about being able to recall the read function once I return to the OS. As per my first question I was thinking of using SetTimer() but I dont know if it is the best possible solution to the problem. Maybe some type of event could work, but I dont think it could be monitored if the program control is with the OS. Does anyone have any advice or answers to my 2 questions? Thanks
ONTIMER: (this all most application need) Since the the data received (using Windows serial communication) is received/sent in the background, you can use the SetTimer() function and just check if any new data has arrived in your OnTimer() event function. How often you need to check depends on the size of the receive buffer you specified when you setup communication (See SetupComm()). To detemine if any data has been received just call ClearCommError(). MULTITHREADING: Of course you could use a seperate thread that uses shared data buffers, protected by critical sections so your threads will not step on each others toes. What I mean by shared buffers is one or more buffers you and the Rx thread both share, when you're reading from a buffer, the RX thread cann't write to it and when the RX thread is writing to it, you cann't read from it. Then all you need to do is calculate approximatly how long it should take to receive X-number of characters and go to sleep for that period of time in your RX thread; when the thread wakes up it then reads the data into the buffer and goes back to sleep (that takes care of the CPU usage problem). You could use two buffers so that the RX thread could be writing into one while you are reading the other one. OR you could use a ring buffer so that you can read from the tail end while the receiver is writing to the head end. (this can be a bit more tricky). The RX thread can inform you that new data has arrived by posting (not sending) a message back to your main thread or by setting an event flag that you must check for every now and then, either in an OnTimer() event function or in the main message loop. FINALY: That should be enough to help solve your problems. FYI: There are some articles at CP (CSerial) and in the MSDN library that use multiple threading for serial communication. GOOD LUCK! INTP "The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes." Andrew W. Troelsen
-
ONTIMER: (this all most application need) Since the the data received (using Windows serial communication) is received/sent in the background, you can use the SetTimer() function and just check if any new data has arrived in your OnTimer() event function. How often you need to check depends on the size of the receive buffer you specified when you setup communication (See SetupComm()). To detemine if any data has been received just call ClearCommError(). MULTITHREADING: Of course you could use a seperate thread that uses shared data buffers, protected by critical sections so your threads will not step on each others toes. What I mean by shared buffers is one or more buffers you and the Rx thread both share, when you're reading from a buffer, the RX thread cann't write to it and when the RX thread is writing to it, you cann't read from it. Then all you need to do is calculate approximatly how long it should take to receive X-number of characters and go to sleep for that period of time in your RX thread; when the thread wakes up it then reads the data into the buffer and goes back to sleep (that takes care of the CPU usage problem). You could use two buffers so that the RX thread could be writing into one while you are reading the other one. OR you could use a ring buffer so that you can read from the tail end while the receiver is writing to the head end. (this can be a bit more tricky). The RX thread can inform you that new data has arrived by posting (not sending) a message back to your main thread or by setting an event flag that you must check for every now and then, either in an OnTimer() event function or in the main message loop. FINALY: That should be enough to help solve your problems. FYI: There are some articles at CP (CSerial) and in the MSDN library that use multiple threading for serial communication. GOOD LUCK! INTP "The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes." Andrew W. Troelsen
thank you for the detailed response. In my original post I failed to mention that I am using shared buffers and as you mentioned it is much better then using one buffer. I have been doing some debugging of the cpu hogging problem and it has come down to be either the infinite for loop that is causing it or the actual worker thread itself. I call the worker thread like this: AfxBeginThread(Read,this); Read() is a static menber function declared as: afx_msg static UINT Read(LPVOID param); As I was told this was how it was supposed to be declared. Here is the Read() function minus the background work:
UINT CprogramDlg::Read(LPVOID param) { for( ;; ) {} return 0; }
Reason I am not including the code within the "for" loop is because after testing I have concluded that even with just the code like this when the Read() function is called from AfxBeginThread() the cpu immediately shoots up to 99% and stays there. So from this I have to conclude that it is either the "infinite for loop" that is causing it or it is the actual thread call that is doing it. It was pointed out to me that an infinite loop in a worker thread "should not" cause the cpu usage to jump up completely like that, but I dont know how true that is. I just want to make sure that it is the infinite loop before I move onto fix the problem by using a timer. Thanks -
thank you for the detailed response. In my original post I failed to mention that I am using shared buffers and as you mentioned it is much better then using one buffer. I have been doing some debugging of the cpu hogging problem and it has come down to be either the infinite for loop that is causing it or the actual worker thread itself. I call the worker thread like this: AfxBeginThread(Read,this); Read() is a static menber function declared as: afx_msg static UINT Read(LPVOID param); As I was told this was how it was supposed to be declared. Here is the Read() function minus the background work:
UINT CprogramDlg::Read(LPVOID param) { for( ;; ) {} return 0; }
Reason I am not including the code within the "for" loop is because after testing I have concluded that even with just the code like this when the Read() function is called from AfxBeginThread() the cpu immediately shoots up to 99% and stays there. So from this I have to conclude that it is either the "infinite for loop" that is causing it or it is the actual thread call that is doing it. It was pointed out to me that an infinite loop in a worker thread "should not" cause the cpu usage to jump up completely like that, but I dont know how true that is. I just want to make sure that it is the infinite loop before I move onto fix the problem by using a timer. ThanksThe worker thread is causing the cpu usage problem, it must go to sleep part of the time if you want it to stop doing that. Even just using WaitCommEvent(...,EV_RXCHAR,...) inside your loop might reduce cpu usage (how much depends on baudrate). I would just use SetupComm(...,dwInQueue,dwOutQueue) and go to sleep for a short time, before reading the data from the rx-buffer. INTP "The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes." Andrew W. Troelsen