《C语言实例教程(PDF格式)》第133章


在OnStartthread()函数中添加如下代码:
void CThreadView::OnStartthread()

// TODO: Add your mand handler code here
HWND hWnd = GetSafeHwnd();
AfxBeginThread(ThreadProc; hWnd; THREAD_PRIORITY_NORMAL);

添加的代码将调用ThreadProc(),这个函数是新添加的线程的控制函 
数,所以还需要在程序中添加这个函数。
在ThreadView。cpp中OnStartthread()的上面添加函数ThreadProc 
()。
l 注意:
…………………………………………………………Page 641……………………………………………………………
l 这个函数是一个全局函数,而并非是CThreadView类的成员函数, 
尽管它在CThreadView类的执行文件中。
在函数ThreadProc()中添加如下代码:
UINT ThreadProc(LPVOID param)

::MessageBox((HWND)param; 〃Thread activated。〃; 〃Thread〃; MB_OK);
return 0;

这个线程实际上并没有作什么,它仅仅报告它被启动了。
在函数前面的两个冒号表明是在调用全局函数,对于Windows程序员 
来说,这通常称为API或SDK调用。
当你运行这个程序后,主窗口出现。选择 “线程”菜单中的 “启动线 
程”菜单选项,系统启动一个线程,并且显示一个消息框,如图12。1 
所示。
图12。 1 线程启动消息框
第二节 线程间通信
通常,一个次要的线程为主线程执行一定的任务,这也暗示这在主线 
程和次要线程之间需要有一个联系的渠道。有几种方法可以完成这些 
联系任务:使用全局变量、使用CEven类或者使用消息。本节将介绍 
这几种方法。
(1) 使用全局变量通信
假定你需要你的程序能够停止线程。你需要一个告诉线程何时停止的 
方法。一种方法是建立一个全局变量,然后让线程监督这个全局变量 
是否为标志线程终止的值。为了实现这种方法,按照如下步骤修改前 
面创建的Thread程序。
1。 在 “线程”菜单中添加菜单项 “停止线程”,ID为 
…………………………………………………………Page 642……………………………………………………………
ID_STOPTHREAD。
2。 为 “停止线程”添加消息处理函数OnStopthread()。
3。 在ThreadView。cpp文件中添加一个全局变量threadController。 
添加方法是在ThreadView。cpp的最上面,在endif下面添加下面的语 
句:
volatile int threadController;
关键字volatile表示你希望这个变量可以被外面使用它的线程修改。
4。 修改OnStartthread()函数,代码如下所示:
void CThreadView::OnStartthread()

// TODO: Add your mand handler code here
threadController = 1;
HWND hWnd = GetSafeHwnd();
AfxBeginThread(ThreadProc; hWnd; THREAD_PRIORITY_NORMAL);

现在你可能已经猜到threadController的值决定线程是否继续。
5。 在OnStopthread()函数中添加下列代码:
threadController = 0;
6。 修改ThreadProc()函数的代码,代码如下:
UINT ThreadProc(LPVOID param)

::MessageBox((HWND)param; 〃Thread activated。〃; 〃Thread〃; MB_OK);
while (threadController == 1)



…………………………………………………………Page 643……………………………………………………………
::MessageBox((HWND)param; 〃Thread stopped。〃; 〃Thread〃; MB_OK);
return 0;

现在线程首先显示一个消息框,告诉用户线程被启动了。然后通过一 
个while循环检查全局变量threadController,等待它的值变成0。尽 
管这个while循环微不足道,但是你在这里可以加上执行你希望的任 
务的代码。
现在编译并运行这个程序,选择 “线程”菜单中的 “启动线程”菜单 
项启动一个线程,这是弹出如图12。1所示的对话框。然后选择 “线 
程”主菜单中的 “停止菜单”菜单项,这时弹出如图12。2所示的对话 
框,告诉用户线程已经终止。
图12。 2 线程关闭消息框
(2) 使用用户自定义消息通信
现在你有了一个简单的用于从主线程中联系附加线程的方法。反过 
来,如何从附加线程联系主线程呢?最简单的实现这种联系的方法是 
在程序中加入用户定义的Windows消息。
首先,要定义用户消息。这一步很容易,例如:
const WM_USERMSG = WM_USER + 100;
WM_USER变量是由Windows定义的,它是第一个有效的用户消息数。因 
为你的程序的其它部分也会使用用户消息,故将新的用户消息 
WM_USERMSG设置为WM_USER+100 。
在定义了用户消息之后,你应当在线程中调用::PostMessage()函数 
来向主线程发送你所需要的消息。一般按照下面的方式调 
用::PostMessage()函数:
::PostMessage((HWND)param; WM_USERMSG; 0; 0);
PostMessage()的四个参数分别是接收消息的窗口的句柄、消息的 
ID、消息的WPARAM和LPARAM参数。
…………………………………………………………Page 644……………………………………………………………
将下面的语句加入到ThreadView。h中CThreadView类声明的上面。
const WM_THREADENDED = WM_USER + 100;
仍然是在此头文件中,在消息映射中加入下列语句,注意要加到 
AFX_MSG的后面和DECLARE_MESSAGE_MAP的前面。
afx_msg LONG OnThreadended();
然后切回到ThreadView。cpp,在类的消息映射中加入下列语句,位置 
在}}AFX_MSG_MAP之后。
ON_MESSAGE(WM_THREADENDED; OnThreadended)
再用下面的语句更改ThreadProc()函数。
UINT ThreadProc(LPVOID param)

::MessageBox((HWND)param; 〃Thread activated。〃; 〃Thread〃; MB_OK);
while (threadController == 1)



::PostMessage((HWND)param; WM_THREADENDED; 0; 0);
return 0;

在CThreadView中添加下面的成员函数。
LONG CThreadView::OnThreadended(WPARAM wParam; LPARAM lParam)

AfxMessageBox(〃Thread ended。〃);
return 0;

…………………………………………………………Page 645……………………………………………………………
图12。 3 线程终止对话框
当你重新运行这个程序时,选择 “线程”主菜单中的 “启动线程”菜 
单选项,弹出一个消息框告诉你线程已经启动。为了结束这个线程, 
选择 “线程”主菜单中的 “停止菜单”菜单选项,这将弹出一个如图 
12。3所示的消息框告诉你线程已经停止。
(3) 使用Event对象通信
一个比较复杂的在两个线程间通信的方法是使用Event对象,在MFC下 
也就是CEvent类对象。一个Event对象可以有两种状态:通信状态和 
非通信状态。线程监视着Event对象的状态,并由此在合适的时间执 
行它们的操作。
创建一个CEvent类的对象很简单,如下:
CEvent threadStart;
实际上,CEvent的构造函数形式如下:
CEvent( BOOL bInitiallyOwn = FALSE; BOOL bManualReset = FALSE;
LPC
小说推荐
返回首页返回目录