Click to See Complete Forum and Search --> : Simple Thread


lyar1031
June 14th, 2005, 02:09 PM
Take a look at this simple Thread App that I got from this website.
It starts a thread when a start button is pressed and the thread is stopped when the stop button is pressed.

Problem: After executing the application. When I try and run the application AGAIN through the degugger you get an error ".../debug/thread.exe/ cannot delete, check to see if the application has write protection or if another process is using this application.

As a result I need to reboot windows everytime I want to run the application. The problem seems to be when I create the events

Here is the Code below:
Thanks

#include "stdafx.h"
#include "Thread.h"
#include "ThreadDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


class CAboutDlg : public CDialog
{
public:
CAboutDlg();

//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA

//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
//}}AFX_VIRTUAL

protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


CThreadDlg::CThreadDlg(CWnd* pParent /*=NULL*/)
: CDialog(CThreadDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CThreadDlg)
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

m_ThreadCreated = false;
m_hSemForStopThread = CreateEvent(0, TRUE, FALSE, 0);
m_hSemForWaitThread = CreateEvent(0, TRUE, FALSE, 0);
}

CThreadDlg::~CThreadDlg()
{
// Trigger thread to stop
SetEvent(m_hSemForStopThread);

// Wait until thread finished
WaitForSingleObject(m_hSemForWaitThread, INFINITE);

// Reset event
ResetEvent(m_hSemForWaitThread);

// Close handles
CloseHandle(m_hSemForStopThread);
CloseHandle(m_hSemForWaitThread);
}

void CThreadDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CThreadDlg)
DDX_Control(pDX, IDC_MESSAGE, m_Message);
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CThreadDlg, CDialog)
//{{AFX_MSG_MAP(CThreadDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_CREATETHREAD, OnCreateThread)
ON_BN_CLICKED(IDC_STOPTHREAD, OnStopThread)
ON_MESSAGE(WM_UPDATE_TEXT, OnMessageText)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


BOOL CThreadDlg::OnInitDialog()
{
CDialog::OnInitDialog();

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);

m_Message.SetWindowText("Thread stopped!");

return TRUE;
}

void CThreadDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

void CThreadDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this);

SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}

HCURSOR CThreadDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}

void CThreadDlg::OnCreateThread()
{
if(!m_ThreadCreated)
{
// Create thread
AfxBeginThread(ThreadFunction, this);

m_ThreadCreated = true;
m_Message.SetWindowText("Thread created!");
}
}

void CThreadDlg::OnStopThread()
{
// Trigger thread to stop
SetEvent(m_hSemForStopThread);

// Wait until thread finished
WaitForSingleObject(m_hSemForWaitThread, INFINITE);

// Reset event
ResetEvent(m_hSemForWaitThread);

m_ThreadCreated = false;

m_Message.SetWindowText("Thread stopped!");
}

UINT CThreadDlg::ThreadFunction(LPVOID pvParam)
{
unsigned long count = 0;
CThreadDlg *pParent = static_cast<CThreadDlg *>(pvParam);

while(true)
{
// Check semaphore for stop thread
if(WaitForSingleObject(pParent->m_hSemForStopThread, 0) == WAIT_OBJECT_0)
{
// Reset event
ResetEvent(pParent->m_hSemForStopThread);

// Set event
SetEvent(pParent->m_hSemForWaitThread);

AfxEndThread(0,TRUE);

return 0;
}

// Send message
CString *pMessage = new CString;

pMessage->Format("Thread is running! Message number %d", ++count);
pParent->PostMessage(WM_UPDATE_TEXT, 0, reinterpret_cast<LPARAM>(pMessage));

Sleep(500);
}
}

LRESULT CThreadDlg::OnMessageText(WPARAM wParam, LPARAM lParam)
{
m_Message.SetWindowText(*reinterpret_cast<CString *>(lParam));
delete reinterpret_cast<CString *>(lParam);
return 0;
}

gstercken
June 14th, 2005, 02:36 PM
Take a look at this simple Thread App that I got from this website.If you edit your post and add code tags, I might take a look at that code.

lyar1031
June 14th, 2005, 02:43 PM
Don;t exactly know what you mean by adding code tags.

However, the problem is in the Destructor. If I comment out the line
WaitForSingleObject(m_hSemForWaitThread, INFINITE);

it seems to be fine!!

Thanks Again

drewdaman
June 14th, 2005, 02:57 PM
Don;t exactly know what you mean by adding code tags.


if you put your code between and [ /code] (without the spaces) the code you post will keep the original formatting and is muche easier to read.. make sure to remove the spaces from the tags i put up there.. i just put spaces so that it wouldn't show up as a code block.

sample code block:
[code]

Andreas Masur
June 14th, 2005, 05:44 PM
[ Redirected thread ]

kuphryn
June 14th, 2005, 06:07 PM
Check out OnStopThread() and the class destructor. One possible issue is m_hSemForWaitThread.

Kuphryn

upashu2
June 22nd, 2005, 07:19 AM
After executing the application. When I try and run the application AGAIN through the degugger you get an error ".../debug/thread.exe/ cannot delete, check to see if the application has write protection or if another process is using this application. See in Task Manager, whether ur application is already listed in process list. It may not be properly terminated.
The reason may be ur destructor:
CThreadDlg::~CThreadDlg()
{
// Trigger thread to stop
SetEvent(m_hSemForStopThread);

// Wait until thread finished
->WaitForSingleObject(m_hSemForWaitThread, INFINITE);

// Reset event
->ResetEvent(m_hSemForWaitThread);

// Close handles
CloseHandle(m_hSemForStopThread);
CloseHandle(m_hSemForWaitThread);
}
you should implement WM_CLOSE or WM_DESTROY and should
write above things there (green lines can be written in
destructor). It is better to put break points at places where
I showed red arrows and run ur program through debugger at first time.