Concurrency and Synchronization

Страницы работы

Содержание работы

Threads--Concurrency and Synchronization

What is a thread?  It’s a piece of executable code which is given its own time slice by the operating system.

A process owns at least one thread, and also owns memory space.   A thread shares the memory space of the process that owns it.   Every thread is owned by some process.  

Usually,  your program’s main thread manages the user interface, and any other threads manage computational tasks.

The class CWinThread wraps the Win32 thread object.   As usual with MFC wrapper classes,  in addition to creating the C++ object, you must call the thread’s  Create function to create the associated Win32 thread. Sometimes one hears  "application thread"  and "system thread".  These are other terms for CWinThread objects and Win32 threads.

Every thread has a function (known as a “thread procedure”) which specifies its task.  There are two kinds of threads: interface threads, and worker threads.  In an interface thread, the thread procedure has a message loop, so it processes Windows messages, while the thread procedure of a worker thread does not.   You cannot send a Windows message to a worker thread.  

When we speak of a “message loop”, we mean something like the code we discussed at the beginning of the semester.  Roughly,

while(msg = GetMessage())

{ DispatchMessage(msg);

}


Possible States of a Thread

Ready.    Waiting for the CPU to give it a time slice so it can execute code.

Running.   Using the CPU right now.

Blocked.    Waiting for input.

Terminated.  Has finished, by executing a return or exit statement, or throwing an unhandled exception.

Scheduler

This is a component of the operating system that switches the states of threads. 

Interthread Communication

Since all threads owned by a process have access to the memory owned by that process, they can communicate by writing to and reading from that memory.   They can treat it as a “bulletin board”. 

One can also communicate with an interface thread by sending it a Windows message.   This can be done using the SendMessage or PostMessage functions, which in MFC appear as member functions in the CWnd class.  You cannot communicate with a worker thread in this way, since its Run does not have a message loop.


 Kruglinksi's Example Program

1.  Make an SDI application, accepting all defaults.   I called mine ThreadTest.

2.  Insert a new dialog, with ID number IDD_COMPUTE, change the OK button to Start (ID_START), and add a progress bar:


The point of the example:  when you press Start, some long computation will begin in a worker thread, and its progress will be shown on the progress bar, and you can interrupt it with the Cancel button at any time.  

3.   Use Class Wizard to add a class CComputeDlg corresponding to this dialog.   Add to this class, button handlers OnStart and OnCancel.

4.  Add global variables (integers) g_nCount and  g_nMaxCount

and initialize them in the constructor of CComputeDlg to 0 and 10000, respectively.  Add a member variable m_nTimer  of type int.


5.  Add OnLButtonDown to the view class,  and make it bring up the dialog:

void CThreadTestView::OnLButtonDown(UINT nFlags, CPoint point)

{

CComputeDlg dlg;

dlg.DoModal();

}

Of course you will have to add #include "ComputeDlg.h"  in your view class .cpp file before you can compile this.   If you like you can add

pDC->TextOut(5,5,"Press the left mouse button here.") in OnDraw.  Now the dialog will come up when you click the mouse.

6.  Map the WM_TIMER message in CComputeDlg:

void CComputeDlg::OnTimer(UINT nIDEvent)

{  CProgressCtrl *pBar =

( CProgressCtrl *)GetDlgItem(IDC_PROGRESS1);

pBar->SetPos(g_nCount *100/ g_nMaxCount);

}

The variable g_nCount is going to measure the progress.  The position needs to be set in percentages, so it has to be scaled.  The thread is going to run until g_nCount == g_nMaxCount.


6.  What do we want the worker thread to do?  We just make up something that will take up time.   Just let the computer count to ten thousand, ten thousand times.   After each count to ten thousand, it increments g_nCount.   When it finishes, it posts a message to the main thread.   That message is a user-defined message (explained below).  The following code will be executed by the worker thread. In this approach, this code is a global function, not belonging to any class. You can put it in the CompDlg.cpp file,  for example.

Похожие материалы

Информация о работе