Click Here!
home account info subscribe login search My ITKnowledge FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Fast Track Visual C++ 6.0 Programming
(Publisher: John Wiley & Sons, Inc.)
Author(s): Steve Holzner
ISBN: 0471312908
Publication Date: 09/01/98

Bookmark It

Search this book:
 
Previous Table of Contents Next


This data object, data, is what we pass to the thread’s procedure. That procedure is not part of the CThreadsView class, and it needs some way of communicating back to us. As outlined previously, we let the thread communicate with us using Windows messages. To do so, we include the Windows handle of the view in the data structure, because we use that handle when we send the notification that the worker is done.

struct SData
 {
    int array[5];
    int max;
    HWND NotifyWindow;                                              ⇐

};

The window handle of the view is stored in the view’s m_hWnd member, so we place that into the HWND member NotifyWindow in the data structure.

void CThreadsView::OnFileFindmax()
 {
    data.array[0] = 0;
    data.array[1] = 1;
    data.array[2] = 2;
    data.array[3] = 3;
    data.array[4] = 4;

    data.max = 0;

    data.NotifyWindow = m_hWnd;                                     ⇐
        .
        .
        .

All that’s left is to start the new thread.

Starting a New Thread

To launch the new thread, we use the AfxBeginThread() procedure.

CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, int
nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags
= 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);

This function takes several parameters: a pointer to the thread procedure, which holds the code the thread is to execute; a parameter that passes on data to the thread, which we make a pointer to our data structure; a parameter that sets the thread priority, which specifies how much processor time it gets; the size of the stack for the new process (setting this parameter to 0 means the new thread gets the same size stack as the present process); thread creation flags; and security attributes.

Here, we start the new thread, passing AfxBeginThread the name of the thread procedure, ThreadProcedure (recall that in C++, function names are pointers), as well as a pointer to the data structure we’ve set up.

void CThreadsView::OnFileFindmax()
 {
    data.array[0] = 0;
    data.array[1] = 1;
    data.array[2] = 2;
    data.array[3] = 3;
    data.array[4] = 4;

    data.max = 0;

    data.NotifyWindow = m_hWnd;

    Thread = AfxBeginThread(ThreadProcedure, &data);                ⇐

}

Now our thread is launched. Our next programming step is to create the thread’s code in ThreadProcedure().

Writing the New Thread’s Thread Procedure

The new thread’s procedure is named ThreadProcedure(), and we’re passed one parameter in that procedure: the pointer pParam we passed to AfxBeginThread(). That pointer points to our data structure, so we can reach the data we’re supposed to work with.

This new procedure, ThreadProcedure(), is not part of the CThreadsView class, so we declare it outside that class’s declaration like this in ThreadsView.h.

// ThreadsView.h : interface of the CThreadsView class
 //
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_THREADSVIEW_H__A880E54F_A6EB_11D1_887F_D42B07C10710__INCLUDED_)
#define AFX_THREADSVIEW_H__A880E54F_A6EB_11D1_887F_D42B07C10710__INCLUDED_

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

UINT ThreadProcedure(LPVOID pParam);                                ⇐

struct SData
{
    int array[5];
    int max;
    HWND NotifyWindow;
};


Handling Thread Errors

Note that the thread procedure returns an unsigned integer; this value is an exit code that the main procedure can access. If a problem occurs, you can pass an error code back to the main procedure this way.


Create ThreadProcedure() now in ThreadsView.cpp.

UINT ThreadProcedure(LPVOID pParam)
{

}

This is where the code the new thread executes goes. We’ve made sure the parameter passed to us, pParam, is a pointer to our data structure, so our first action is to cast that pointer into a new pointer of type SData*, not LPVOID, to avoid compiler errors when we use that pointer.

UINT ThreadProcedure(LPVOID pParam)
 {
    SData* pData = (SData*)pParam;                                  ⇐
      .
      .
      .

}

Now we can find the maximum value in the array. We set up a loop to loop over all the members of the array.

UINT ThreadProcedure(LPVOID pParam)
 {
    SData* pData = (SData*)pParam;

    for(int loop_index = 0; loop_index <= 4; loop_index++){
              .
              .
              .
  }

}

Each member of the array can be reached with the pData pointer now as pData->array[loop_index], so we search for the maximum value in the array.

UINT ThreadProcedure(LPVOID pParam)
 {
    SData* pData = (SData*)pParam;

    for(int loop_index = 0; loop_index <= 4; loop_index++){
        if(pData->array[loop_index] > pData->max)                    ⇐
              .
              .
              .
  }

}

After finding the maximum value, we return that result.

Returning Data from the Thread

When we find the maximum, we place it into the max member of the data structure.

UINT ThreadProcedure(LPVOID pParam)
 {
    SData* pData = (SData*)pParam;

    for(int loop_index = 0; loop_index <= 4; loop_index++){
        if(pData->array[loop_index] > pData->max)
            pData->max = pData->array[loop_index];              ⇐
    }
         .
         .
         .

}

We have now returned data from the thread. The rest of the program can read the result from the max data member, which is why we set up our SData structure in the first place.

The new thread’s work is done, and we have to notify the program’s view object.

Notifying the Program on Thread Completion

We notify the view object by sending a Windows message to it. The view’s window handle is stored in the data structure’s NotifyWindow member, so we send a message to the view with ::PostMessage(). In our call to that function, WM_MAX is the new Windows message we’ve created, and the last two parameters are the usual Windows message parameters, wParam and lParam, which we set to 0.

UINT ThreadProcedure(LPVOID pParam)
 {
    SData* pData = (SData*)pParam;

    for(int loop_index = 0; loop_index <= 4; loop_index++){
        if(pData->array[loop_index] > pData->max)
            pData->max = pData->array[loop_index];
    }

    ::PostMessage(pData->NotifyWindow, WM_MAX, 0, 0);             ⇐
      .
      .
      .

}

We will soon learn to set up a new Windows message and how to handle it in the view, but first we must make sure we end the thread procedure appropriately by returning an integer value. We won’t make use of this exit code, so we just return a value of 0.

UINT ThreadProcedure(LPVOID pParam)
 {
    SData* pData = (SData*)pParam;

    for(int loop_index = 0; loop_index <= 4; loop_index++){
        if(pData->array[loop_index] > pData->max)
            pData->max = pData->array[loop_index];
    }

    ::PostMessage(pData->NotifyWindow, WM_MAX, 0, 0);

    return 0;                                                       ⇐

}

That completes the thread procedure. In it, we’ve examined the data in the data structure, found the maximum value in the array and stored it in the data structure’s element named max, and sent a Windows message to the view. All that’s left is to handle that new Windows message in the view class, which we turn to now.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.