![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
To access the contents, click the chapter and section titles.
Fast Track Visual C++ 6.0 Programming
Starting the ThreadsThe 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 views 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 EventsTo create the event object that coordinates the two threads, we add a new membera handle named Flagto the SData structure. struct SData { int array[5]; int max; int min; HANDLE flag; ⇐ HWND NotifyWindow; }; Then, in the views 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 events security attributes if we want to set up security for the event (which we dont 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 events name (we dont 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 ProceduresThe 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 threadMinThreadis 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 ProcedureStart 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; ⇐ } Weve 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 MessagesWe 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 views OnDraw() function. void CDoubleThreadsView::OnDraw(CDC* pDC) { CDoubleThreadsDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDC->TextOut(0, 0, pDoc->text); ⇐ }
|
![]() |
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. |