您的位置:首页 > 编程语言 > C语言/C++

在VC++6.0下如何用事件与线程通讯使线程同步和终止

2005-10-03 11:49 435 查看
出处:http://www.bloghome.cn/topics/vc/4_18.htm

在VC++6.0下如何用事件与线程通讯使线程同步和终止
Windows 提供两种线程,辅助线程(又叫工作线程)和用户界面线程。Micrisoft Foundation Class (MFC)库对两种线程都支持。一个用户界面线程有窗口,因此它有自己消息循环辅助线程没有窗口,所以它不需要处理消息。Windows主线程(我们的应用程序)可以有许多方法跟辅助线程通讯。本文主要阐述了如何利用事件启动辅助线程和终止辅助线程。

-.事件

事件(event)是一种Windows为线程同步提供的核心对象,一个事件用进程里唯一的32位句柄标识。它的句柄可以被进程中所有的线程共享。一个事件可以是有信号状态(或true)或者无信号状态(或false)。事件有两种类型: 手工重置和自动重置 。我们利用手工重置来启动或终止辅助线程。下面将通过示例给出于详细说明。

二.示例程序构建

现在我们编写一个具有辅助线程程序,辅助线程包含一个很消耗CPU的计算循环。我人希望在用户的辅助线程开始计算后,能继续处理来自主线程的通讯;否则的话,用户就不能取消线程的计算工作了。而且,我们用一个进度指示器来显示当前的百分比状态,如图所示:

1.运行AppWizard来创建MultiThread。选择Single Document,取消对Printing And Print Preview,其它都 接受默认设置。

2.用对话框创建对话框资源IDD_COMPUTE。按图所示建立资源。

Cancel按钮的ID为默认值,但Start按钮的值为IDC_START。对于进度指示器,使用默认ID为IDC_PROGRESS1。

3.用ClassWizard创建CComputeDlg类。ClassWizard会把新建的IDD_COMPUTE资源连接起来。类产生后,加一个WM-TIMER消息控制函数,再加入IDC_START 和IDCANCEL 按钮的BN_CLICKED消息控制函数,并接受默认名字OnStart和OnCancel。

4.在CComprtDlg类中加入两个数据成员。编辑文件ComputeDlg.h,加入下面的私有数据成员:

int m_nTimer;

公有数据成员

enum {nMaxCount =10000};

有计算过程中,CComputeDlg类中的全局变量g_nCount不断地递增的, 用它与“常量”nMaxCount相除作为完成的百分比.

5.在ComputeDlg.cpp文件中声明变量

HANDLE hEvent [2];//事件句柄

6.编写ComprteDlg.cpp文件中的OnStart函数。当用户按下Start按钮时,OnStart函数就会被自动调用。

void CComprteDig::OnStart()

{

m_nTimer = SetTimer(1,100,NULL);//十分之一秒

ASSETR(m_nTimer!=0);

GetDlgItem (IDC_START)->EnableWindow(FALSE);

SetEvent (hEvent[0]);

}

7.编写ComputeDlg.cpp文件中的OnCancel函数。

void CComputeDig::OnCancel()

{

SetEvent (hEvent[1]);

CDialog::OnCancel();

}

8.用ClassWizard在ComprteDig.cpp中加入OnInitDialog函数并编写函数内容。

BOOL CComputeDlg::OnlnitDialog()

{

CDialog::OnlnitDialog();

ResetEvent(hEvent[0]);

ResetEvent(hEvent[1]);

AfxBeginThread (ComputeThreadProc,GetSafeHWnd());

return TRUE;

}

9.编写ComputeDlg.cpp文件中的OnTimer函数。 当计时器被启动时, 进度指示器的位置就会根据m_nCount的值进行设置。

void CComputeDdlg:: OnTimer (UINT nIDEvent)

{

CProgressCtrl*pBar = (CProgressCtrl*)GetDlgltem(IDC_PRIGRESS1);

PBar->SetPos(g-nCount*100/nMaxCount);

CDialog::OnTimer(nIDEvent);

}

10.在ComputeDlg.cpp文件的前面定义全局变量g_nCount和hEvent。

int g_nCount =0;

HANDLE hEvent [2];

UINT ComputeThreadProc (LPVOID pParam);

11.编写全局线程函数如下;

UINT ComputeThreadProc (LPVOID pParam)

{

volatile int nTemp;

int Status, StatusAgain;

Status =:: WaitForMultipleObjects (2 , hEvent,FALSE, INFINITE);

if (Status = = WAIT_OBJECT_0){

Reset (hEvent[0]);

for (g_nCount =0; g_nCount <10000; nTemp++);

StatusAgain =:: WaitForMultipleObject (2, hEvent,FALSE,0);//立即返回

if (StatusAgain = =(WAIT_OBJECT_0+1) )break;

}

::PostMessage ((HWND) pParam,WM_THREADFINISHED,0,0);

}

else ::PostMessage ((HWND) pParam,WM_THREADFINISHED,0,0);

g_nCount =0;

return 0;

}

12.在ComputeDlg.h.定义WM_THREADFINISHED用户消息并在ComputeDlg.cpp中手工加入相应的消息函数。

#define WM_THREADFINISHED WM_USER +5

在CComputeDlg类中加入私有函数说明:

private:

LRESULT OnThreadFinished (WPARAM wParam,LPARAMIParma);

在ComputeDlg.cpp中BEGIN_MESSAGE_MAP

(CComputeDlg, CDialog)后面但在

//{{AFX_MSG_MAP(CComputeDlg)前面加入下列一条语句

ON_MESSAGE(WM_THREADFINISHED,OnThreadFinished)

如下:

BEGIN_MESSAGE_MAP(CcomputeDlg,CDialog)

ON_MESSAGE(WM_THREADFINISHED,OnThreadFinished)

//{{AFX_MSG_MAP(CComputeDlg)

ON_BN_CLICKED(IDC_START,OnStart)

ON_WM_TIMER()

//}}AFX_MSG_MAP

END_MESSAGE_MAP

LRESULT CComputeDlg:: OnThreadFinished (WPARAM wParam,LPARAM IParam)

{

CDialog::OnK();

return 0;

}

13.编辑MultiThreadView,cpp里的CMultiThreadView类。在OnDraw虚函数加入下列用于提示信息的语句:

pDC ->TextOut (0,0,"Click the left mouse button here!");

用ClassWizard加进OnLButtonDown函数以处理WM_LBUTTONDOWN消息,并在其中加入如下代码:

void CMultiThreadView :: OnLButtonDown (UINT nFlags CPoint point)

{

CComputeDlg dlg;

dlg.DoModal();

CView::OnLButtonDown(nFlgs,point);

}

在MultiThreadView.cpp里加入如下说明:

extern HANDLE hEvent[2]

用ClassWizard加进虚拟函数OninitialUpdate,并在其中加入如下代码:

void CmultiThreadView:: OninitialUpdate()

{

CView::OnlnitialUpdate();

//TODO:Add your specialized code here and / or call the base class

hEvent [0] = CreateEvent(NULL, TRUE, FALSE, "Start Thread");

hEvent [1] = CreateEvent(NULL, TRUE, FALSE, "Teminate Thread");

}

另外在MultiThreadView.cpp文件中加入如下的#include语句#include"ComputeDlg.h"

14.编译并运行应用程序。当鼠标指针落在视窗中,请按下鼠标左键,比时就可在屏幕上弹出对话框。然后请试一下按钮,之后再按一下Cancel按钮。 查看进度指示器就知道线程执行完终止还是没执行完终止。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: