-
[RESOLVED] How to set a timer for a workthread?
I cerate a workthread for serial port operation. I want the thread to read the serial port once per 100ms, then send the received data to a Dialog.But the thread which install a timer need a message loop,the work thread hasn't it's own message queue.How to slove the problem?
Thanks!
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by tjuzhangrui
But the thread which install a timer need a message loop,the work thread hasn't it's own message queue.
Implement the message queue yourself.
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by PadexArt
Implement the message queue yourself.
... to transform it in a GUI thread.
-
Re: How to set a timer for a workthread?
You don't need a timer to read/send your data from serial port.
After the using of CreateFile() function you need to configure the COMMTIMEOUTS structure.
Code:
// Set the Timeouts to specify the behavior of reads and writes.
COMMTIMEOUTS ct;
ct.ReadIntervalTimeout = 100;
ct.ReadTotalTimeoutMultiplier = 0;
ct.ReadTotalTimeoutConstant = 0;
ct.WriteTotalTimeoutMultiplier = 10;
ct.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hGPSPort, &ct))
{
AfxMessageBox(L"Error Setting Comm Timeouts.", MB_OK, 0);
CloseHandle(hGPSPort);
hGPSPort = INVALID_HANDLE_VALUE;
}
If you need to send your read data from your serial read thread to the main thread (the dialog's thead) you need to define a own message and to use PostMessage(method).
Code:
// in the top of CPP file
#define MY_THREAD_MSG WMAPP + 1
--------
// in the message map
ON_MESSAGE(MY_THREAD_MSG, OnStringPosted)
------------
/* Post the message from thread */
void CyourProgramDlg::PostTheMessage(LPCTSTR pszText)
{
PostMessage(MY_THREAD_MSG, 0, (LPARAM) pszText);
}
-----------
LRESULT CyourProgramDlg::OnStringPosted( WPARAM wParam, LPARAM lParam)
{
CString strLine=_T("");
strLine.Format(_T("%s\r\n"), (LPCTSTR)lParam);
int nLength = m_ctrlLogFile.GetWindowTextLengthW();
m_ctrlLogFile.SetSel(nLength, nLength);
m_ctrlLogFile.ReplaceSel((LPCTSTR)lParam);
return 0;
}
Enjoy! :thumb:
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by ovidiucucu
... to transform it in a GUI thread.
No, just to handle the interesting messages. :)
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by PadexArt
No, just to handle the interesting messages. :)
Everytime I made a GUI thread I handled only the interesting messages... :D ;)
-
Re: How to set a timer for a workthread?
Wouldn't it be enough to use
?
-
Re: How to set a timer for a workthread?
Using MSComm ActiveX could solve many problems.
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by tjuzhangrui
I want the thread to read the serial port once per 100ms, then send the received data to a Dialog.But the thread which install a timer need a message loop,the work thread hasn't it's own message queue.How to slove the problem?
Quote:
Originally Posted by Maximus
After the using of CreateFile() function you need to configure the COMMTIMEOUTS structure.
Quote:
Originally Posted by MSDN
ReadIntervalTimeout
Maximum time allowed to elapse between the arrival of two bytes on the communications line, in milliseconds. During a ReadFile operation, the time period begins when the first byte is received. If the interval between the arrival of any two bytes exceeds this amount, the ReadFile operation is completed and any buffered data is returned. A value of zero indicates that interval time-outs are not used.
WriteTotalTimeoutConstant
Constant used to calculate the total time-out period for write operations, in milliseconds. For each write operation, this value is added to the product of the WriteTotalTimeoutMultiplier member and the number of bytes to be written.
Thus, I don't think that's going to help the problem here.
Quote:
Originally Posted by Padan
Wouldn't it be enough to use?
An interesting suggestion...
Quote:
Originally Posted by tjuzhangrui
But the thread which install a timer need a message loop,the work thread hasn't it's own message queue.
So what about making it a GUI thread?
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by tjuzhangrui
I cerate a workthread for serial port operation. I want the thread to read the serial port once per 100ms, then send the received data to a Dialog.But the thread which install a timer need a message loop,the work thread hasn't it's own message queue.How to slove the problem?
Quote:
Originally Posted by cilu
Thus, I don't think that's going to help the problem here.
So what about making it a GUI thread?
Marius (cilu), from tjuzhangrui's problem I understand that he has an application with two thread, the main thread for the application dialog and the second for serial port reading.
First, he asks us how he can read the serial port once per 100 ms and I recomanded him to use COMMTIMEOUTS structure in the function of the second thread.
The second part of tjuzhangrui's problem it's the data sending to the main thread (on the dialog).
So, why my advices doesn't helps him on this problem?
-
Re: How to set a timer for a workthread?
using the sleep will suffice ..
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by AshokParikh
Using MSComm ActiveX could solve many problems.
Yeah right :D That thing was designed with VB6 in mind. I wouldn't use it unless I had a gun pointed at my head. Besides, using ActiveX implies a lot of overhead that cannot be justified in this case.
-
Re: How to set a timer for a workthread?
Thanks All!
I think that Sleep() will be a good solution for my problem.
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by Maximus_X
You don't need a timer to read/send your data from serial port.
After the using of CreateFile() function you need to configure the COMMTIMEOUTS structure.
Code:
// Set the Timeouts to specify the behavior of reads and writes.
COMMTIMEOUTS ct;
ct.ReadIntervalTimeout = 100;
ct.ReadTotalTimeoutMultiplier = 0;
ct.ReadTotalTimeoutConstant = 0;
ct.WriteTotalTimeoutMultiplier = 10;
ct.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hGPSPort, &ct))
{
AfxMessageBox(L"Error Setting Comm Timeouts.", MB_OK, 0);
CloseHandle(hGPSPort);
hGPSPort = INVALID_HANDLE_VALUE;
}
If you need to send your read data from your serial read thread to the main thread (the dialog's thead) you need to define a own message and to use PostMessage(method).
Code:
// in the top of CPP file
#define MY_THREAD_MSG WMAPP + 1
--------
// in the message map
ON_MESSAGE(MY_THREAD_MSG, OnStringPosted)
------------
/* Post the message from thread */
void CyourProgramDlg::PostTheMessage(LPCTSTR pszText)
{
PostMessage(MY_THREAD_MSG, 0, (LPARAM) pszText);
}
-----------
LRESULT CyourProgramDlg::OnStringPosted( WPARAM wParam, LPARAM lParam)
{
CString strLine=_T("");
strLine.Format(_T("%s\r\n"), (LPCTSTR)lParam);
int nLength = m_ctrlLogFile.GetWindowTextLengthW();
m_ctrlLogFile.SetSel(nLength, nLength);
m_ctrlLogFile.ReplaceSel((LPCTSTR)lParam);
return 0;
}
Enjoy! :thumb:
Thanks!
Your method that processing the message is valuable for me.
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by Maximus_X
Code:
// ....
/* Post the message from thread */
void CyourProgramDlg::PostTheMessage(LPCTSTR pszText)
{
PostMessage(MY_THREAD_MSG, 0, (LPARAM) pszText);
}
This won't work reliably, since the pointer being posted in the message will not necessarily point to anything meaningful by the time the message is handled. For example:
Code:
//...
{
CString str;
str.Format("Hi from a thread");
PostTheMessage( str ):
}
// str now goes out of scope and is destroyed ...
Since str has gone out of scope, and has been destroyed, by the time that the message handler is executed, the LPARAM of the handler will be pointing to invalid memory. Bad things follow.
Mike
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by tjuzhangrui
Thanks!
Your method that processing the message is valuable for me.
You're wellcome. I'm glad that my sample helps you.
Quote:
Originally Posted by MikeAThon
This won't work reliably, since the pointer being posted in the message will not necessarily point to anything meaningful by the time the message is handled. For example:
Code:
//...
{
CString str;
str.Format("Hi from a thread");
PostTheMessage( str ):
}
// str now goes out of scope and is destroyed ...
Since str has gone out of scope, and has been destroyed, by the time that the message handler is executed, the LPARAM of the handler will be pointing to invalid memory. Bad things follow.
Mike
Mike, I have posted here a part of my program that works fine on a Windows CE application. Perhaps it's not perfect, but I met no problems on that application (it's a real time application ;) ).
I invite you to post here your best solution. :rolleyes:
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by Maximus_X
Mike, I have posted here a part of my program that works fine on a Windows CE application. Perhaps it's not perfect, but I met no problems on that application (it's a real time application ;) ).
I invite you to post here your best solution. :rolleyes:
You have been lucky as it happened for the memory address to not be reused/acquired by the time your thread processed the message. What you've done here is very similar to returning he address of a local function variable.
The correct solution is to allocate a char buffer, send that to the thread and have the thread delete it when finished.
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by PadexArt
You have been lucky as it happened for the memory address to not be reused/acquired by the time your thread processed the message. What you've done here is very similar to returning he address of a local function variable.
The correct solution is to allocate a char buffer, send that to the thread and have the thread delete it when finished.
Thanks!We can simply create the buffer on the heap to avoid the mistake.
But there's another question. A thread allocated the memory, and another free the memory.This is against the advice that "Allocate and free memory in the same module", it's that considerable in practice?
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by tjuzhangrui
This is against the advice that "Allocate and free memory in the same module", it's that considerable in practice?
That rule refers to modules (such as DLLs) and not threads. With a DLL you can have manny complications as the language in which it was written may be completelly different but this is not the case with threads.
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by Maximus_X
Mike, I have posted here a part of my program that works fine on a Windows CE application. Perhaps it's not perfect, but I met no problems on that application (it's a real time application ;) ).
I invite you to post here your best solution. :rolleyes:
Indeed, as pointed out by PadexArt, you have been lucky. He gives a good analogy that your technique is similar to a function's return of a pointer to a local stack variable.
Your technique might have worked so far because of a quirk in the way it was used. If you call if like so, with a literal string in the parameter:
Code:
PostTheMessage( _T("Hi from a thread") );
then it might work for the reason that the memory for the literal string will remain intact throughout the life of the program. But that's pure luck.
Mike
-
Re: How to set a timer for a workthread?
MikeAThon and PadexArt thanks for your sugestions.
I appreciate it. ;)
Looking again on my code, I have remember that the serial connection it was made in the main thread and in the second thread I just used ReadFile() and so on (the second thread function it's static UINT CmyAppDlg::SerialReadThread( LPVOID lParam )).
Regards.
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by Maximus_X
... Looking again on my code, I have remember that the serial connection it was made in the main thread and in the second thread I just used ReadFile() and so on (the second thread function it's static UINT CmyAppDlg::SerialReadThread( LPVOID lParam )).
Regards.
Well, I'm a bit confused, for the reason that your post seems really unrelated to the points that PadexArt and I were trying to make. It doesn't matter how the thread was started, or the signature of the thread function. If you are trying to PostMessage a char* across threads, as it appears you are doing to post the string obtained from ReadFile, then it's always necessary to ensure that the char* remains valid and unique until some indeterminate time in the future when the message handler is actually executed.
But if you're satisfied with the outcome, then that's good enough for me.
Mike
-
Re: How to set a timer for a workthread?
Quote:
Originally Posted by MikeAThon
Well, I'm a bit confused, for the reason that your post seems really unrelated to the points that PadexArt and I were trying to make. It doesn't matter how the thread was started, or the signature of the thread function. If you are trying to PostMessage a char* across threads, as it appears you are doing to post the string obtained from ReadFile, then it's always necessary to ensure that the char* remains valid and unique until some indeterminate time in the future when the message handler is actually executed.
But if you're satisfied with the outcome, then that's good enough for me.
Mike
Well Mike, thanks again for your advice. I appreciate it. I understand what you meed.
I'll keep in my mind and I'll apply it on the code.
Regards,
Silviu.