在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按钮。 查看进度指示器就知道线程执行完终止还是没执行完终止。
在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按钮。 查看进度指示器就知道线程执行完终止还是没执行完终止。
相关文章推荐
- 如何终止线程的运行(C/C++)
- 如何终止java线程
- 如何:创建和终止线程(C# 编程指南)
- 线程,如何通过pthread_t这个线程id判断线程是否已经终止
- 如何终止Java线程
- 如何跨线程触发COM事件
- 如何终止java线程
- 如何在基于 MFC 的 ActiveX 控件激发事件,在 Visual c + + 中的启动另一个线程
- 如何终止java线程
- 如何终止java线程
- 线程同步和线程通讯
- Android中的 事件流----浅析安卓中的动与静(三) 线程间通讯
- 如何终止线程的运行(C/C++)
- python高效编程技巧13(如何在线程之间实现事件通知)
- 如何终止java线程
- [C# 线程处理系列]专题五:线程同步——事件构造
- java如何终止线程(整合自网络)
- Qt学习之如何启动和终止一个线程
- android NDK中如何终止线程
- 如何终止Java线程