Help with threads
-
AndrewG1231 wrote:
So, my question...in order to get this sequence to run several times, say 5 times, and update the window how would I use
PostMessage()
? Or if I have misunderstood something please let me know.See here for more.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
Thanks for the link to the article and I have tried to implement the
PostMessage()
in my code. However, I am still having problems trying to get it to execute more than once and update the window (looping the code is not working). After reading your suggested article, I am still not sure how to do this correctly, can you help? My code is as follows.void CDlg_SpectrumAnalyzer::OnBtnClickedRun()
{
PostMessage(WM_COMMAND,IDC_SPECTRUM_START,0);
}Yes, this is a "Run" button that sends the message and it executes correctly if called only a single time.
-
Thanks for the link to the article and I have tried to implement the
PostMessage()
in my code. However, I am still having problems trying to get it to execute more than once and update the window (looping the code is not working). After reading your suggested article, I am still not sure how to do this correctly, can you help? My code is as follows.void CDlg_SpectrumAnalyzer::OnBtnClickedRun()
{
PostMessage(WM_COMMAND,IDC_SPECTRUM_START,0);
}Yes, this is a "Run" button that sends the message and it executes correctly if called only a single time.
AndrewG1231 wrote:
...it executes correctly if called only a single time.
What happens when the handler is called a second time?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
-
AndrewG1231 wrote:
...it executes correctly if called only a single time.
What happens when the handler is called a second time?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
When it is called the second time I encounter some code for checking the state of the instrument my program is controlling. You can see the whole block of code this belongs to in the first post of this thread.
if(!m_inst->StartOperation())
{
MessageBox("The Instrument is Currently in use by another function");
return;
}I thought this indicated that the previous thread wasn't terminating before the message posted again and I tried to use
Sleep()
to delay the call, but this did not work. I encountered the same situation or the window did not update. I also tried to use theWaitForSingleObject()
, but this failed as well. -
When it is called the second time I encounter some code for checking the state of the instrument my program is controlling. You can see the whole block of code this belongs to in the first post of this thread.
if(!m_inst->StartOperation())
{
MessageBox("The Instrument is Currently in use by another function");
return;
}I thought this indicated that the previous thread wasn't terminating before the message posted again and I tried to use
Sleep()
to delay the call, but this did not work. I encountered the same situation or the window did not update. I also tried to use theWaitForSingleObject()
, but this failed as well.Look this over. It's from memory and completly untested so there may be a few small details left out, but it should give you good idea of how primary and secondary threads communicate.
BEGIN_MESSAGE_MAP(CMyDialog, CDiaog)
ON_BN_CLICKED(IDC_BUTTON, OnClick)
END_MESSAGE_MAP()void CMyDialog::Acq_Data( void )
{
while (1)
{
// if a STOP event has been signaled [m_pEventStopRequested.SetEvent()]
if (WaitForSingleObject(m_pEventStopRequested->m_hObject, 0U) == WAIT_OBJECT_0)
{
// let OnClick() know that the secondary thread is not running
m_pEventThreadDone->SetEvent();return; } else ADCdbInquire(...); // this functon can post messages back to the primary thread }
}
/* static */ UINT CMyDialog::Acq_Data( LPVOID lpVoid )
{
CMyDialog *pDlg = (CMyDialog *) lpVoid;pDlg->Acq\_Data(); // once here, the secondary thread is done so post a message // back to the primary thread to tell it to enable the button return 0;
}
// put these in CMyDialog
CWinThread *m_pThread = NULL;
CEvent *m_pEventStopRequested = new CEvent(FALSE, TRUE); // stop requested (initially no)?
CEvent *m_pEventThreadDone = new CEvent(TRUE, TRUE); // thread done (initially yes)?void CMyDialog::OnClick()
{
// if the secondary thread is not running
if (WaitForSingleObject(m_pEventThreadDone->m_hObject, 0U) == WAIT_OBJECT_0)
{
// at this point, you could disable the button that
// started this so that it could not be clicked again// set the STOP and DONE events to nonsignaled (haven't happened yet) m\_pEventStopRequested->ResetEvent(); m\_pEventThreadDone->ResetEvent(); // start the secondary thread m\_pThread = AfxBeginThread(Acq\_Data, this, THREAD\_PRIORITY\_HIGHEST); }
}
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
-
Look this over. It's from memory and completly untested so there may be a few small details left out, but it should give you good idea of how primary and secondary threads communicate.
BEGIN_MESSAGE_MAP(CMyDialog, CDiaog)
ON_BN_CLICKED(IDC_BUTTON, OnClick)
END_MESSAGE_MAP()void CMyDialog::Acq_Data( void )
{
while (1)
{
// if a STOP event has been signaled [m_pEventStopRequested.SetEvent()]
if (WaitForSingleObject(m_pEventStopRequested->m_hObject, 0U) == WAIT_OBJECT_0)
{
// let OnClick() know that the secondary thread is not running
m_pEventThreadDone->SetEvent();return; } else ADCdbInquire(...); // this functon can post messages back to the primary thread }
}
/* static */ UINT CMyDialog::Acq_Data( LPVOID lpVoid )
{
CMyDialog *pDlg = (CMyDialog *) lpVoid;pDlg->Acq\_Data(); // once here, the secondary thread is done so post a message // back to the primary thread to tell it to enable the button return 0;
}
// put these in CMyDialog
CWinThread *m_pThread = NULL;
CEvent *m_pEventStopRequested = new CEvent(FALSE, TRUE); // stop requested (initially no)?
CEvent *m_pEventThreadDone = new CEvent(TRUE, TRUE); // thread done (initially yes)?void CMyDialog::OnClick()
{
// if the secondary thread is not running
if (WaitForSingleObject(m_pEventThreadDone->m_hObject, 0U) == WAIT_OBJECT_0)
{
// at this point, you could disable the button that
// started this so that it could not be clicked again// set the STOP and DONE events to nonsignaled (haven't happened yet) m\_pEventStopRequested->ResetEvent(); m\_pEventThreadDone->ResetEvent(); // start the secondary thread m\_pThread = AfxBeginThread(Acq\_Data, this, THREAD\_PRIORITY\_HIGHEST); }
}
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
Thanks for the suggestions! However, this piece of code is causing me to get the error, "A nonstatic member reference must be relative to a specific object". I tried to use
this->
beforem_pEventStopRequested->m_hObject
but it did not solve the problem. I have the declaration for theCEvent
in the constructor, but I am not sure to what object it is referring.if (WaitForSingleObject(m_pEventStopRequested->m_hObject, 0U) == WAIT_OBJECT_0)
{
// let OnClick() know that the secondary thread is not running
m_pEventThreadDone.SetEvent();
return;
}Would you happen to know what object it is referring to?
-
Thanks for the suggestions! However, this piece of code is causing me to get the error, "A nonstatic member reference must be relative to a specific object". I tried to use
this->
beforem_pEventStopRequested->m_hObject
but it did not solve the problem. I have the declaration for theCEvent
in the constructor, but I am not sure to what object it is referring.if (WaitForSingleObject(m_pEventStopRequested->m_hObject, 0U) == WAIT_OBJECT_0)
{
// let OnClick() know that the secondary thread is not running
m_pEventThreadDone.SetEvent();
return;
}Would you happen to know what object it is referring to?
AndrewG1231 wrote:
However, this piece of code is causing me to get the error, "A nonstatic member reference must be relative to a specific object".
What is the exact error number?
AndrewG1231 wrote:
m_pEventThreadDone.SetEvent();
Should be:
m_pEventThreadDone->SetEvent();
That, and adding a return value, is all I had to do to get the code to compile.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
-
AndrewG1231 wrote:
However, this piece of code is causing me to get the error, "A nonstatic member reference must be relative to a specific object".
What is the exact error number?
AndrewG1231 wrote:
m_pEventThreadDone.SetEvent();
Should be:
m_pEventThreadDone->SetEvent();
That, and adding a return value, is all I had to do to get the code to compile.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
Here is the exact compiler message of the error.
Dlg_SpectrumAnalyzer.cpp(150): error C2227: left of '->m_hObject' must point to class/struct/union/generic type
1>Dlg_SpectrumAnalyzer.cpp(153): error C2227: left of '->SetEvent' must point to class/struct/union/generic type
1>Dlg_SpectrumAnalyzer.cpp(154): error C2561: 'CDlg_SpectrumAnalyzer::Acq_Data' : function must return a valueHowever, I implemented you suggestion a bit differently. I did not use
void Acq_DAta(void)
instead I have incorporated everything in the following member.UINT CDlg_SpectrumAnalyzer::Acq_Data(LPVOID pParam)
{CDlg\_SpectrumAnalyzer \*dlg =(CDlg\_SpectrumAnalyzer\*) pParam; HWND hdlg = dlg->GetSafeHwnd(); // start data ACQ while(1) { if (WaitForSingleObject(m\_pEventStopRequested->m\_hObject, 0U) == WAIT\_OBJECT\_0) { // let OnClick() know that the secondary thread is not running m\_pEventThreadDone->SetEvent(); return; } else { dlg->m\_inst->ADCdbRead(dlg->m\_AcqChan,dlg->m\_MaxFreq\*2,dlg->m\_BuffSize,dlg->m\_fulldata,dlg->m\_halfdata); while(dlg->m\_Continue && ! dlg->m\_inst->m\_Flags.Halt) dlg->m\_inst->ADCdbInquire(dlg- >m\_halfdata,hdlg,MSG\_DRAW\_SPECTRUM); dlg->m\_inst->ADCdbStop(); //release instrument dlg->m\_inst->EndOperation(); return 1; } }
}
Here is the button control code.
void CDlg_SpectrumAnalyzer::OnBnClickedRun()
{
// TODO: Add your control notification handler code here
if (WaitForSingleObject(m_pEventThreadDone->m_hObject, 0U) == WAIT_OBJECT_0)
{
// at this point, you could disable the button that
// started this so that it could not be clicked again// set the STOP and DONE events to nonsignaled (haven't happened yet) m\_pEventStopRequested->ResetEvent(); m\_pEventThreadDone->ResetEvent(); // start the secondary thread m\_pThread = AfxBeginThread(Acq\_Data, this, THREAD\_PRIORITY\_HIGHEST); }
}
Have I done something foolish in the way I was trying to use your suggestion?
-
Here is the exact compiler message of the error.
Dlg_SpectrumAnalyzer.cpp(150): error C2227: left of '->m_hObject' must point to class/struct/union/generic type
1>Dlg_SpectrumAnalyzer.cpp(153): error C2227: left of '->SetEvent' must point to class/struct/union/generic type
1>Dlg_SpectrumAnalyzer.cpp(154): error C2561: 'CDlg_SpectrumAnalyzer::Acq_Data' : function must return a valueHowever, I implemented you suggestion a bit differently. I did not use
void Acq_DAta(void)
instead I have incorporated everything in the following member.UINT CDlg_SpectrumAnalyzer::Acq_Data(LPVOID pParam)
{CDlg\_SpectrumAnalyzer \*dlg =(CDlg\_SpectrumAnalyzer\*) pParam; HWND hdlg = dlg->GetSafeHwnd(); // start data ACQ while(1) { if (WaitForSingleObject(m\_pEventStopRequested->m\_hObject, 0U) == WAIT\_OBJECT\_0) { // let OnClick() know that the secondary thread is not running m\_pEventThreadDone->SetEvent(); return; } else { dlg->m\_inst->ADCdbRead(dlg->m\_AcqChan,dlg->m\_MaxFreq\*2,dlg->m\_BuffSize,dlg->m\_fulldata,dlg->m\_halfdata); while(dlg->m\_Continue && ! dlg->m\_inst->m\_Flags.Halt) dlg->m\_inst->ADCdbInquire(dlg- >m\_halfdata,hdlg,MSG\_DRAW\_SPECTRUM); dlg->m\_inst->ADCdbStop(); //release instrument dlg->m\_inst->EndOperation(); return 1; } }
}
Here is the button control code.
void CDlg_SpectrumAnalyzer::OnBnClickedRun()
{
// TODO: Add your control notification handler code here
if (WaitForSingleObject(m_pEventThreadDone->m_hObject, 0U) == WAIT_OBJECT_0)
{
// at this point, you could disable the button that
// started this so that it could not be clicked again// set the STOP and DONE events to nonsignaled (haven't happened yet) m\_pEventStopRequested->ResetEvent(); m\_pEventThreadDone->ResetEvent(); // start the secondary thread m\_pThread = AfxBeginThread(Acq\_Data, this, THREAD\_PRIORITY\_HIGHEST); }
}
Have I done something foolish in the way I was trying to use your suggestion?
AndrewG1231 wrote:
Have I done something foolish in the way I was trying to use your suggestion?
Yes, you are trying to access non-static members from within a static function. Check my code again. Note there are two
Acq_Data()
functions."One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
-
AndrewG1231 wrote:
Have I done something foolish in the way I was trying to use your suggestion?
Yes, you are trying to access non-static members from within a static function. Check my code again. Note there are two
Acq_Data()
functions."One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
So, I saw the two
Acq_Data()
functions and I ran into the following problem with the use of thedlg
pointer and thehdlg
entry in theADCdbInquire(...)
member which is of the typeHWND
.dlg->m_inst->ADCdbRead(dlg->m_AcqChan,dlg->m_MaxFreq*2,dlg->m_BuffSize,dlg->m_fulldata,dlg->m_halfdata);
while(dlg->m\_Continue && ! dlg->m\_inst->m\_Flags.Halt) dlg->m\_inst->ADCdbInquire(dlg->m\_halfdata,hdlg,MSG\_DRAW\_SPECTRUM);
dlg->m_inst->ADCdbStop();
//release instrument
dlg->m_inst->EndOperation();I tried to combine the call to function and the actual code to enable the process, apparently, this leads to the compiler issue. How can I get the handle? I did try just using
HWND hdlg = GetSafeHwnd();
and eliminating all thedlg
code which compiled fine but led to the following runtime error.Unhandled exception at 0x012d2ba9 in WinSTM.exe: 0xC0000005: Access violation reading location 0x000002af.
Your patience has been amazing..usually by now I have received some type of comment about my newbie-ness. Thanks! :-D
-
So, I saw the two
Acq_Data()
functions and I ran into the following problem with the use of thedlg
pointer and thehdlg
entry in theADCdbInquire(...)
member which is of the typeHWND
.dlg->m_inst->ADCdbRead(dlg->m_AcqChan,dlg->m_MaxFreq*2,dlg->m_BuffSize,dlg->m_fulldata,dlg->m_halfdata);
while(dlg->m\_Continue && ! dlg->m\_inst->m\_Flags.Halt) dlg->m\_inst->ADCdbInquire(dlg->m\_halfdata,hdlg,MSG\_DRAW\_SPECTRUM);
dlg->m_inst->ADCdbStop();
//release instrument
dlg->m_inst->EndOperation();I tried to combine the call to function and the actual code to enable the process, apparently, this leads to the compiler issue. How can I get the handle? I did try just using
HWND hdlg = GetSafeHwnd();
and eliminating all thedlg
code which compiled fine but led to the following runtime error.Unhandled exception at 0x012d2ba9 in WinSTM.exe: 0xC0000005: Access violation reading location 0x000002af.
Your patience has been amazing..usually by now I have received some type of comment about my newbie-ness. Thanks! :-D
AndrewG1231 wrote:
...I ran into the following problem with the use of the
dlg
pointer...From whence comes the
dlg
pointer?AndrewG1231 wrote:
which compiled fine but led to the following runtime error.
Unhandled exception at 0x012d2ba9 in WinSTM.exe: 0xC0000005: Access violation reading location 0x000002af.
Sounds like a
NULL
pointer. Use the debugger, set a breakpoint on the call toADCdbRead()
, and check the values ofdlg
,m_inst
, andm_Flags
."One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
-
AndrewG1231 wrote:
...I ran into the following problem with the use of the
dlg
pointer...From whence comes the
dlg
pointer?AndrewG1231 wrote:
which compiled fine but led to the following runtime error.
Unhandled exception at 0x012d2ba9 in WinSTM.exe: 0xC0000005: Access violation reading location 0x000002af.
Sounds like a
NULL
pointer. Use the debugger, set a breakpoint on the call toADCdbRead()
, and check the values ofdlg
,m_inst
, andm_Flags
."One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
Hey, it has been a little while, but your suggestions were very helpful in diagnosing my problem. I am currently working on a solution, but wanted to share my thanks. :)
-
Hey, it has been a little while, but your suggestions were very helpful in diagnosing my problem. I am currently working on a solution, but wanted to share my thanks. :)
Glad you're progressing.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous