CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Apr 2008
    Posts
    93

    Unhappy 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.

  2. #2
    Join Date
    Jun 2002
    Location
    Stockholm, Sweden
    Posts
    1,641

    Resolved 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

  3. #3
    Join Date
    Apr 2008
    Posts
    93

    Re: Ending Specific Thread

    Quote 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.

  4. #4
    Join Date
    Jun 2002
    Location
    Stockholm, Sweden
    Posts
    1,641

    Re: Ending Specific Thread

    Quote 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

  5. #5
    Join Date
    Apr 2008
    Posts
    93

    Re: Ending Specific Thread

    Quote 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?

  6. #6
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    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).

  7. #7
    Join Date
    Apr 2008
    Posts
    93

    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.

  8. #8
    Join Date
    Apr 2008
    Posts
    93

    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?

  9. #9
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Ending Specific Thread

    Quote 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 );
    }

  10. #10
    Join Date
    Apr 2008
    Posts
    93

    Re: Ending Specific Thread

    ok i will show him what you say when he come back.

    thanks Arjay..

  11. #11
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    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
  •  





Click Here to Expand Forum to Full Width

Featured