thread in a dialog bar

I have a subroutine in a dialog bar that polls a device and displays the current status on a dialog bar. This keeps running for the entire course of the application. The controls it uses are all read only. I have been trying to use a thread to run this subroutine but keep having trouble with memory leaks and hanging up when closing. How can I close the dialogbar down without the problems I stated.

Better yet if someone can give a brief code snippet to do it that would be great.

This is what I do
CWinThread* myWorkerThread;

OnDialogBar initializtion
{
myWorkerThread = AfxBeginThread(ThreadFunction, this);
}

UINT CPositionBar::ThreadFunction(LPVOID pvParam)
{
bool StayHere;
clock_t goal;
CPositionBar* pParent = (CPositionBar*)(pvParam);

while(running) //running static boolean
{
pParent->ThreadFunction();
goal = 1000 + clock();
while( goal > clock() ); //poll every second
}
return 0;
}
void CPositionBar::ThreadFunction()
{
GetData();
}

void CPositionBar::OnClose()
{
// If we get here, are are closing the view
myWorkerThread->m_bAutoDelete = FALSE;
running = FALSE;
WaitForSingleObject(myWorkerThread->m_hThread, INFINITE;
delete myWorkerThread;

CInitDialogBar::OnClose();
}
[1457 byte] By [Troy Erickson] at [2007-11-18 17:38:56]
# 1 Re: thread in a dialog bar
[Moved thread]
Andreas Masur at 2007-11-9 13:55:49 >
# 2 Re: thread in a dialog bar
You might want to take a look at the following FAQs for a general overview...

How to create a worker thread? (http://www.dev-archive.com/forum/showthread.php?s=&threadid=231241)
How to end a thread? (http://www.dev-archive.com/forum/showthread.php?s=&threadid=231242)
How to use member functions as thread functions? (http://www.dev-archive.com/forum/showthread.php?s=&threadid=231246)
How to access UI elements from a thread in MFC? (http://www.dev-archive.com/forum/showthread.php?s=&threadid=231250)
Andreas Masur at 2007-11-9 13:57:00 >
# 3 Re: thread in a dialog bar
Instead of using a boolean to check for the termination event, simply use an event...take a look at the following example:

class CFoo
{
public:
CFoo();
~CFoo();

private:
HANDLE m_hEventForStopThread;
HANDLE m_hEventForWaitThread;

static UINT ThreadFunction(LPVOID* pvParam);
};

CFoo::CFoo()
{
// Create event
HANDLE m_hEventForStopThread = CreateEvent(0, TRUE, FALSE, 0);
HANDLE m_hEventForWaitThread = CreateEvent(0, TRUE, FALSE, 0);

// Start thread
AfxBeginThread(ThreadFunction, this);
}

CFoo::~CFoo()
{
// Trigger thread to stop
::SetEvent(m_hEventForStopThread);

// Wait until thread finished
::WaitForSingleObject(m_hEventForWaitThread, INFINITE);

// Close handles
::CloseHandle(m_hEventForStopThread);
::CloseHandle(m_hEventForWaitThread);
}

UINT CFoo::ThreadFunction(LPVOID* pvParam)
{
CFoo *pParent = static_cast<CFoo *>(pvParam);

while(true)
{
// Check event for stop thread
if(::WaitForSingleObject(pParent->m_hEventStopThread, 0) == WAIT_OBJECT_0)
{
// Set event
::SetEvent(pParent->m_hEventWaitThread);

return 0;
}

// Do your processing
}
}
Andreas Masur at 2007-11-9 13:57:59 >
# 4 Re: thread in a dialog bar
Unhandled exception at 0x77fa167c in MyApp.exe: 0xC0000008: An invalid HANDLE was specified.

I get this when I reach the ::CloseHandle for both events.
If i take them out I get memory leak.
Troy Erickson at 2007-11-9 13:58:54 >
# 5 Re: thread in a dialog bar
Well...I assume you copy-pasted parts of my code into different places of your code...can you probably post your code here?
Andreas Masur at 2007-11-9 13:59:53 >
# 6 Re: thread in a dialog bar
/// PositionBar.h: interface for the MyDialogBar class.
//
//////////////////////////////////////////////////////////////////////

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include "LedButton.h"
#include "initdialogbar.h"
#include "resource.h"



// CPositionBar window

class CPositionBar : public CInitDialogBar
{
DECLARE_DYNAMIC(CPositionBar)

// Construction
public:
CPositionBar();
static BOOL running;
void GetData();
void sleep( clock_t wait );
void OnToggleDisplay();

// Attributes
public:
bool InputStatus[8];
bool OutputStatus[8];
bool XStatus[8];
bool YStatus[8];
bool ZStatus[8];
bool WStatus[8];
CWinThread *myWorkerThread;
// Operations
public:

// Dialog Data
//{{AFX_DATA(CPositionBar)
enum { IDD = CG_IDD_POSITIONANDIO };
CStatic m_ZLen;
CStatic m_YLen;
CStatic m_WLen;
CStatic m_XLen;
CLedButton m_Output8;
CLedButton m_Output7;
CLedButton m_Output6;
CLedButton m_Output5;
CLedButton m_Output4;
CLedButton m_Output3;
CLedButton m_Output2;
CLedButton m_Output1;
CLedButton m_MotorZ;
CLedButton m_MotorY;
CLedButton m_MotorX;
CLedButton m_MotorW;
CLedButton m_MotionZ;
CLedButton m_MotionY;
CLedButton m_MotionW;
CLedButton m_LimitCWZ;
CLedButton m_LimitCWY;
CLedButton m_LimitCWX;
CLedButton m_LimitCWW;
CLedButton m_LimitCCWZ;
CLedButton m_LimitCCWY;
CLedButton m_LimitCCWX;
CLedButton m_LimitCCWW;
CLedButton m_Input8;
CLedButton m_Input7;
CLedButton m_Input6;
CLedButton m_Input5;
CLedButton m_Input4;
CLedButton m_Input3;
CLedButton m_Input2;
CLedButton m_Input1;
CLedButton m_HomeZ;
CLedButton m_HomeY;
CLedButton m_HomeX;
CLedButton m_HomeW;
CLedButton m_ErrorZ;
CLedButton m_ErrorY;
CLedButton m_ErrorX;
CLedButton m_ErrorW;
CLedButton m_MotionX;
CStatic m_PositionW;
CStatic m_PositionX;
CStatic m_PositionY;
CStatic m_PositionZ;
CStatic m_Analog1;
CStatic m_Analog2;
CStatic m_Analog3;
CStatic m_Analog4;
CStatic m_Analog5;
CStatic m_Analog6;
CStatic m_Analog7;
//}}AFX_DATA

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CPositionBar)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
//}}AFX_VIRTUAL

// Implementation
public:
virtual BOOL OnInitDialogBar();
virtual ~CPositionBar();

// Generated message map functions
protected:
//{{AFX_MSG(CPositionBar)
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:

afx_msg void OnIdViewPositionandio();
afx_msg void OnClose();
bool m_bAlready;

private:
HANDLE m_hEventForStopThread;
HANDLE m_hEventForWaitThread;

static UINT ThreadFunction(LPVOID pvParam);
void ThreadFunction();

};

partial of the .cpp

CPositionBar::~CPositionBar()
{
// Trigger thread to stop
::SetEvent(m_hEventForStopThread);

// Wait until thread finished
::WaitForSingleObject(m_hEventForWaitThread, INFINITE);

// Close handles
::CloseHandle(m_hEventForStopThread);
::CloseHandle(m_hEventForWaitThread);



}

UINT CPositionBar::ThreadFunction(LPVOID pvParam)
{
clock_t goal;

CPositionBar* pParent = (CPositionBar*)(pvParam);

while(true)
{
// Check event for stop thread
if(::WaitForSingleObject(pParent->m_hEventForStopThread, 0) == WAIT_OBJECT_0)
{
// Set event
::SetEvent(pParent->m_hEventForWaitThread);

return 0;
}

pParent->ThreadFunction();

goal = 1000 + clock();
while( goal > clock() )
;


} /* loop */

return 0;
}
void CPositionBar::ThreadFunction()
{
GetData(); //whole bunch of setwindowtext to readonly text boxes
}

void CPositionBar::OnToggleDisplay()
{
if (!running)
{
running = true;
HANDLE m_hEventForStopThread =CreateEvent(0, TRUE, FALSE, 0);
HANDLE m_hEventForWaitThread = CreateEvent(0, TRUE, FALSE, 0);

myWorkerThread = AfxBeginThread(ThreadFunction, this);

}
else
{
running = false;

}
}
Troy Erickson at 2007-11-9 14:01:03 >
# 7 Re: thread in a dialog bar
You are working on different handles since you create local variables inside the function 'OnToggleDisplay()'...change the function to

void CPositionBar::OnToggleDisplay()
{
if(!running)
{
running = true;
m_hEventForStopThread =CreateEvent(0, TRUE, FALSE, 0);
m_hEventForWaitThread = CreateEvent(0, TRUE, FALSE, 0);

myWorkerThread = AfxBeginThread(ThreadFunction, this);
}
else
{
running = false;
}
}
Andreas Masur at 2007-11-9 14:01:57 >
# 8 Re: thread in a dialog bar
Hmm... Andreas already found the bug... But I have a suggestion too:
-Rewrite the strange timer-loop (which btw is very CPU consuming). There is a much easier way to accomplish what you're trying to do and without wasting CPU time:
UINT CPositionBar::ThreadFunction(LPVOID pvParam)
{
CPositionBar* pParent = (CPositionBar*)(pvParam);

// Check event for stop thread
while (::WaitForSingleObject(pParent->m_hEventForStopThread, 1000) == WAIT_TIMEOUT)
{
pParent->ThreadFunction();
}

return 0;
}

I left out the SetEvent(m_hEventForWaitThread) statement, because I normally wouldn't need it when one can wait on a thread handle itself. This is perhaps not possible with the AfxBeginThread function (depending on if it closes the handle before the thread function goes out of scope or not).

Hope it helps,
Jonas
j0nas at 2007-11-9 14:03:01 >
# 9 Re: thread in a dialog bar
Thanks for you help. The problem is this. It gets hung up because the setwindowtext in the last few statements of the thread have not completed (my theory) because if I retry and break it stops at an assert error in the setwindowtext in the windows core files. So the thread is finishing but the window did not finish its messaging.(my theory again) Do I have to clear the message queue or is there someway to check if it is truly done.

Another thing I can do if you have a suggestion. If I stop it for example by a menu option ex view dialogbar. It stops just fine it only has a problem when exiting the application. If I go file exit or hit the x in the upper right corner is there an event that will allow me to turn off the thread before it dismantles itself.
Troy Erickson at 2007-11-9 14:03:59 >