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 Search this book:
Previous | Table of Contents | Next
#### Starting the Threads The menu item the user selects to start the threads is in the File menu: Find max and min. We start the program by filling the array, setting the maximum value to 0, and setting the window to notify by placing the view’s window handle in the NotifyWindow member.
    void CDoubleThreadsView::OnFileFindmaxandmin()
     {
        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;
            .
            .
            .
In addition, we start the thread that looks for the maximum value, MaxThread.
    void CDoubleThreadsView::OnFileFindmaxandmin()
     {
        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;                                     ⇐
        MaxThread = AfxBeginThread(MaxThreadProcedure, &data);       ⇐
            .
            .
            .
Before starting the other thread, MinThread, however, we want to reset the event it waits for. In this way, that thread waits until we set the event before doing its work. #### Setting and Resetting Events To create the event object that coordinates the two threads, we add a new member—a handle named Flag—to the SData structure.
    struct SData
     {
        int array[5];
        int max;
        int min;
        HANDLE flag;                                                    ⇐
        HWND NotifyWindow;

    };
Then, in the view’s constructor, we make this into an event object with the CreateEvent() function.
    CDoubleThreadsView::CDoubleThreadsView()
     {
        data.flag = CreateEvent(NULL, FALSE, FALSE, NULL);             ⇐

    }
In this case, the first parameter we pass to CreateEvent() is a pointer to the event’s security attributes if we want to set up security for the event (which we don’t here). It is followed by the manual-rest flag (which we set to FALSE), then the initial state of the event (which we set to FALSE so the event is reset initially), and a pointer to the event’s name (we don’t have a name for the event here, so we leave that parameter at NULL). This creates a new event in the flag member of the data structure. Before we start the new thread, MinThread, we reset that event with the ResetEvent() function.
    void CDoubleThreadsView::OnFileFindmaxandmin()
     {
        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;
        MaxThread = AfxBeginThread(MaxThreadProcedure, &data);
        ResetEvent(data.flag);                                          ⇐
          .
          .
          .
    }
Finally, we start the new thread, MinThread.
    void CDoubleThreadsView::OnFileFindmaxandmin()
     {
        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;
        MaxThread = AfxBeginThread(MaxThreadProcedure, &data);
        ResetEvent(data.flag);

        MinThread = AfxBeginThread(MinThreadProcedure, &data);          ⇐

    }
The next step is to write the thread procedures, which we turn to now. #### Writing the Thread Procedures The MaxThreadProcedure() function is similar to the last example in which we find the maximum value in the array in the data structure, but with one difference. When we find the maximum and just before we return, we set the event the other thread—MinThread—is waiting for, so it can continue. To set the event, we use the SetEvent() function.
    UINT MaxThreadProcedure(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);

        SetEvent(pData->flag);                                          ⇐
        return 0;

    }
Setting the event lets MinThread proceed. In fact, write the code for that procedure now. #### Writing the MinThread Procedure Start the new procedure as usual.
    UINT MinThreadProcedure(LPVOID pParam)
    {

    }
We begin this procedure by casting the pointer passed to us from LPVOID to SData* to avoid compiler problems.
    UINT MinThreadProcedure(LPVOID pParam)
     {
        SData* pData = (SData*)pParam;                                  ⇐
            .
            .
            .
Next, we wait until the event pData->flag is set, and we do that with the Wait-ForSingleObject() function. We indicate that this function should wait an infinite amount of time for that flag to be set.
    UINT MinThreadProcedure(LPVOID pParam)
     {
        SData* pData = (SData*)pParam;

        WaitForSingleObject(pData->flag, INFINITE);                       ⇐
          .
          .
          .

    }
Then we simply find the minimum in the array and place that value in the data->min member.
    UINT MinThreadProcedure(LPVOID pParam)
     {
        SData* pData = (SData*)pParam;

        WaitForSingleObject(pData->flag, INFINITE);

        pData->min = pData->max;                                       ⇐

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

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

        return 0;                                                      ⇐

    }
We’ve finished the two thread procedures. Those procedures, when done, send back WM_MAX and WM_MIN to the view, and we handle those messages next. #### Handling the Windows Messages We connect the WM_MAX message to a new function, OnMaxFound(), and WM_MIN to OnMinFound().
    IMPLEMENT_DYNCREATE(CDoubleThreadsView, CView)

    BEGIN_MESSAGE_MAP(CDoubleThreadsView, CView)
        //{{AFX_MSG_MAP(CDoubleThreadsView)
        ON_COMMAND(ID_FILE_FINDMAXANDMIN, OnFileFindmaxandmin)
        ON_MESSAGE(WM_MAX, OnMaxFound)                                  ⇐
        ON_MESSAGE(WM_MIN, OnMinFound)                                  ⇐
        //}}AFX_MSG_MAP
        // Standard printing commands
        ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
        ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
        ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)

    END_MESSAGE_MAP()
In OnMaxFound(), we format the maximum value and add it to a string in the document, prefaced with the string “Maximum value in array = ”, and terminate the thread.
    void CDoubleThreadsView::OnMaxFound(WPARAM wParam, LPARAM lParam)
     {
        CDoubleThreadsDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);

        char FormattedString[100];
        wsprintf(FormattedString, “Maximum value in array = %d, ”, data.max);
        pDoc->text = FormattedString;

        TerminateThread(MaxThread, 0);

        Invalidate();

    }
When MinThread finds the minimum of the array, we add that to our text string in OnMinFound(), along with the string “minimum value in array = ”, and terminate MinThread.
    void CDoubleThreadsView::OnMinFound(WPARAM wParam, LPARAM lParam)
     {
        CDoubleThreadsDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);

        char FormattedString[100];
        wsprintf(FormattedString, “minimum value in array = %d ”, data.min);
        pDoc->text += FormattedString;

        TerminateThread(MinThread, 0);

        Invalidate();

    }
Finally, we display the text string from the document in the view’s OnDraw() function.
    void CDoubleThreadsView::OnDraw(CDC* pDC)
     {
        CDoubleThreadsDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);

        pDC->TextOut(0, 0, pDoc->text);                       ⇐

    }
Figure 9.2 Using the onMouseOut event.
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.