-
September 23rd, 2008, 06:05 AM
#1
Ending Specific Thread
this is the sample code, because too big so i cant attach it. Sorry.
im using thread to run the function.
Code:
// Dialog1Dlg.cpp : implementation file
//
#include "stdafx.h"
#include "Dialog1.h"
#include "Dialog1Dlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
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)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDialog1Dlg dialog
CDialog1Dlg::CDialog1Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CDialog1Dlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CDialog1Dlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CDialog1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDialog1Dlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDialog1Dlg, CDialog)
//{{AFX_MSG_MAP(CDialog1Dlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_NEXT_PAGE, OnNextPage)
ON_BN_CLICKED(IDC_PREV_PAGE, OnPrevPage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDialog1Dlg message handlers
BOOL CDialog1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
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);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
CDC *pDrawing1;
pDrawing1 = GetDC();
memdcDrawing1.CreateCompatibleDC(pDrawing1);
bmDrawing1.CreateCompatibleBitmap(pDrawing1,400,400);
memdcDrawing1.SelectObject(&bmDrawing1);
ReleaseDC(pDrawing1);
CDC *pDrawing2;
pDrawing2 = GetDC();
memdcDrawing2.CreateCompatibleDC(pDrawing2);
bmDrawing2.CreateCompatibleBitmap(pDrawing2,400,400);
memdcDrawing2.SelectObject(&bmDrawing2);
ReleaseDC(pDrawing2);
CDC *pBlank;
pBlank = GetDC();
memdcBlank.CreateCompatibleDC(pBlank);
bmBlank.CreateCompatibleBitmap(pBlank,400,400);
memdcBlank.SelectObject(&bmBlank);
ReleaseDC(pBlank);
q=0;
return TRUE; // return TRUE unless you set the focus to a control
}
void CDialog1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CDialog1Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CDialog1Dlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CDialog1Dlg::OnNextPage()
{
q=1;
if(q==1)
{
AfxBeginThread(Thread1,(LPVOID)this);
}
//else
//{
//AfxBeginThread(Blank,(LPVOID)this);
//CClientDC dc(this);
//dc.BitBlt(100,100,700,700,&memdcBlank,0,0,SRCCOPY);
//AfxEndThread(0);
//}
TRACE("q = %d\n",q);
}
void CDialog1Dlg::OnPrevPage()
{
// TODO: Add your control notification handler code here
q=2;
if(q==2)
{
AfxBeginThread(Thread2,(LPVOID)this);
}
//else
//{
//AfxBeginThread(Blank,(LPVOID)this);
//CClientDC dc(this);
//dc.BitBlt(100,100,700,700,&memdcBlank,0,0,SRCCOPY);
//AfxEndThread(0);
//}
TRACE("q = %d\n",q);
}
UINT CDialog1Dlg::Thread1(LPVOID lp)
{
CDialog1Dlg *pDlg1;
pDlg1 = (CDialog1Dlg*)lp;
CClientDC dc(pDlg1);
if(pDlg1->q==1)
{
while(true)
{
pDlg1->Drawing1();
dc.BitBlt(100,100,700,700,(&pDlg1->memdcDrawing1),0,0,SRCCOPY);
}
return true;
}
if(pDlg1->q!=1)
{
while(true)
{
//AfxEndThread(0);
pDlg1->Blank();
dc.BitBlt(100,100,700,700,(&pDlg1->memdcBlank),0,0,SRCCOPY);
}
return true;
}
}
UINT CDialog1Dlg::Thread2(LPVOID lp)
{
CDialog1Dlg *pDlg2;
pDlg2 = (CDialog1Dlg*)lp;
CClientDC dc(pDlg2);
if(pDlg2->q==2)
{
while(true)
{
pDlg2->Drawing2();
dc.BitBlt(100,100,700,700,(&pDlg2->memdcDrawing2),0,0,SRCCOPY);
}
return true;
}
if(pDlg2->q!=2)
{
while(true)
{
//AfxEndThread(0);
pDlg2->Blank();
dc.BitBlt(100,100,700,700,(&pDlg2->memdcBlank),0,0,SRCCOPY);
}
return true;
}
}
void CDialog1Dlg::Drawing1()
{
CPen GreenPen(PS_SOLID,2,RGB(0,255,0));
CBrush GreenBrush(RGB(0,255,0));
memdcDrawing1.SelectObject(&GreenPen);
memdcDrawing1.SelectObject(&GreenBrush);
memdcDrawing1.Rectangle(0,0,400,400);
}
void CDialog1Dlg::Drawing2()
{
CPen BlackPen(PS_SOLID,2,RGB(0,0,0));
CBrush BlackBrush(RGB(0,0,0));
memdcDrawing2.SelectObject(&BlackPen);
memdcDrawing2.SelectObject(&BlackBrush);
memdcDrawing2.Rectangle(0,0,400,400);
}
void CDialog1Dlg::Blank()
{
}
UINT CDialog1Dlg::Blank(LPVOID lp)
{
CDialog1Dlg *pBLANK;
pBLANK = (CDialog1Dlg*)lp;
CClientDC dc(pBLANK);
while(true)
{
pBLANK->Blank();
dc.BitBlt(100,100,700,700,(&pBLANK->memdcBlank),0,0,SRCCOPY);
}
return true;
}
What im trying to do is creating a dialog box and i have three button Close, Next Page and Previous Page. when Next Page is pressed, variable q will have a value of 1 and when Previous Page is pressed, it will have a value of 2. variable q I initially set a value of 0 at OnInitDialog()
a green box will appear when Next Page is pressed and when Previous Page is pressed, a black box will overlap green box. but my program run both green box thread and black box thread at the same time, but i only want to run one thread and stop the other thread.
I try some method like blanking the screen and AfxEndThread (which i dont know whether is correct), etc...
i really need help on it.
-
September 23rd, 2008, 06:36 AM
#2
Re: Ending Specific Thread
Sorry, but I cannot understand why you would need to use threads to display a green and black box on a dialog.
If threads really is the solution you want to use, I recommend not to forcibly kill any threads.
Instead loop on a volatile variable and set the variable to end the thread.
Code:
volatile BOOL keeprunning=TRUE;
ThreadFunc() {
while(keeprunning) {
...
}
}
Nobody cares how it works as long as it works
-
September 23rd, 2008, 10:05 AM
#3
Re: Ending Specific Thread
Originally Posted by zerver
Sorry, but I cannot understand why you would need to use threads to display a green and black box on a dialog.
If threads really is the solution you want to use, I recommend not to forcibly kill any threads.
Instead loop on a volatile variable and set the variable to end the thread.
Code:
volatile BOOL keeprunning=TRUE;
ThreadFunc() {
while(keeprunning) {
...
}
}
ok
but my lecturer told me to stop or pause the specific thread and let other run thread when certain button is pressed
the green box and black box is only example, the actual picture is much more complicated, which uses lots of memory DC.
-
September 23rd, 2008, 11:04 AM
#4
Re: Ending Specific Thread
Originally Posted by ashwarrior
but my lecturer told me to stop or pause the specific thread and let other run thread when certain button is pressed
When the loop exits, the thread is stopped.
If you want to make sure the thread has terminated, use WaitForSingleObject(threadhandle) after setting the keeprunning flag to FALSE.
If you want to pause a thread, you could make the thread wait for an event object. Read the CreateEvent() documentation for more info.
Nobody cares how it works as long as it works
-
September 23rd, 2008, 11:32 AM
#5
Re: Ending Specific Thread
Originally Posted by zerver
When the loop exits, the thread is stopped.
If you want to make sure the thread has terminated, use WaitForSingleObject(threadhandle) after setting the keeprunning flag to FALSE.
If you want to pause a thread, you could make the thread wait for an event object. Read the CreateEvent() documentation for more info.
ok btw i have possibility that i will switch back to previous thread, how do i resume it?
-
September 23rd, 2008, 11:37 AM
#6
Re: Ending Specific Thread
See the SimpleThread samples in my signature line. They show how to start, pause, resume, stop and cleanup threads. (If you don't see my signature, turn signatures on in the UserCP).
-
September 23rd, 2008, 12:04 PM
#7
Re: Ending Specific Thread
ok thanks arjay,
another question, if i pause thread A and resume or start thread B, will both image from A and B run at the same time? or do i need to cover thread A image?
btw from Simple Thread: Part I, i just have to take note of this two part. am i right?
Code:
// Implementation (in StartStopDlg.h)
protected:
enum ThreadStatus { TS_STOPPED, TS_START, TS_PAUSE, TS_RESUME };
INT m_ThreadState;
// CStartStopDlg dialog (in StartStopDlg.cpp)
CStartStopDlg::CStartStopDlg(CWnd* pParent /*=NULL*/)
: CDialog(CStartStopDlg::IDD, pParent)
, m_ThreadState( TS_STOPPED )
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
Code:
// Toggles the Start/Pause/Resume state and sets the button text
INT CStartStopDlg::ToggleSPRState( )
{
if( TS_RESUME == m_ThreadState )
{
m_ThreadState = TS_START;
}
m_ThreadState++;
CString sButtonText = _T("");
switch( m_ThreadState )
{
case TS_START:
sButtonText = _T("Pause");
break;
case TS_PAUSE:
sButtonText = _T("Resume");
break;
case TS_RESUME:
sButtonText = _T("Pause");
break;
default:
ASSERT( 0 ); // We shouldn't reach this
}
// Set button text
m_btnStartPause.SetWindowText( sButtonText );
return m_ThreadState;
}
Last edited by ashwarrior; September 23rd, 2008 at 09:16 PM.
-
September 24th, 2008, 01:34 AM
#8
Re: Ending Specific Thread
arjay,
my lecturer saw your method but he think that it is not the correct method, because the program i doing does not have any buttons (GUI) on it.
as the buttons is located at the hardware prototype and we only reading value coming out from all the buttons, btw all different CPU.
is there any other method?
-
September 24th, 2008, 02:52 PM
#9
Re: Ending Specific Thread
Originally Posted by ashwarrior
arjay,
my lecturer saw your method but he think that it is not the correct method, because the program i doing does not have any buttons (GUI) on it.
Ask him to look at SimpleThread Part II. This sample has code to start, pause, resume, and stop a thread. The threading code is abstracted from the UI code. So it doesn't really matter if you connect the threading code to a UI with buttons or a console app that prompts the user.
Code:
//+------------------------------------------------------
// Start, pause, and resume button handler
//+------------------------------------------------------
void CStartStopDlg::OnBnClickedStartPauseResume()
{
m_btnStartPauseResume.EnableWindow( FALSE );
m_btnStop.EnableWindow( FALSE );
switch( ToggleSPRState( ) )
{
case TS_START:
// Start the thread
m_LogMgr.Start( GetSafeHwnd( ) );
break;
case TS_PAUSE:
// Pause the thread
m_LogMgr.Pause( );
break;
case TS_RESUME:
// Resume the thread
m_LogMgr.Resume( );
break;
default:
ASSERT( 0 ); // We shouldn't reach this
}
m_btnStartPauseResume.EnableWindow( TRUE );
m_btnStop.EnableWindow( TRUE );
}
//+------------------------------------------------------
// Stop button handler
//+------------------------------------------------------
void CStartStopDlg::OnBnClickedStop()
{
m_btnStartPauseResume.EnableWindow( FALSE );
m_btnStop.EnableWindow( FALSE );
// Stop the thread
m_LogMgr.Stop( );
// Reset the startpause button
ResetSPRState( );
// Reset the original string
m_LogMgr.AddLogEntryStringWSync( _T("Original log entry string that will be replaced"));
m_btnStartPauseResume.EnableWindow( TRUE );
}
-
September 25th, 2008, 03:06 AM
#10
Re: Ending Specific Thread
ok i will show him what you say when he come back.
thanks Arjay..
-
September 25th, 2008, 09:52 AM
#11
Re: Ending Specific Thread
I should have mentioned this earlier, but in the button handler code snippets I provided notice the calls to m_LogMgr.Start(), m_LogMgr.Pause and so on. These are calls into the log manager class which encapsulates the threading functionality.
This keeps the threading code out of the UI (i.e separation of responsibility). Because of this you can replace the GUI with another form of User Interface such as the console. The threading code doesn't know about or care which UI drives it.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|