1、基础知识:
1)进程 (process):是一个具有一定功能的程序在一个数据集合的一次动态执行过程。进程由正文段,用户数据段以及系统数据段共同组成一个执行环境,与处理器、存储器和外设等资源的分配和回收相对应,进程是计算机系统资源的使用主体,也是操作系统分配资源的基本单位。
2)线程:在多个进程并发执行时,进程切换的开销比较大,影响了进程间通信的效率。因此提出了更小的能独立运行的基本单位——线程。线程时进程的一个实体,是cpu调度和分配的基本单位,除了一些在运行中必不可少的资源,线程不拥有系统资源,但是线程可以和同属于一个进程的其他线程共享进程的全部资源。
3)传统的操作系统中,进程是分配资源、独立调度和分配的基本单位,引入线程后,线程当作调度和分配的基本单位,进程仍然是拥有资源的基本单位。
4)关系:为了让进程完成一些工作,进程必须至少占有一个线程,所以线程是描述进程内的执行,正是线程负责执行包含在进程的地址空间的代码。
5)互锁函数: 运行在用户模式,它能保证当一个线程访问一个变量时,其他线程无法访问此变量,以确保变量值的唯一性。这种访问方式叫做原子访问。如InterlockedIncrement(LPLONG)等等。
6)事件对象:事件对象运行在内核模式,利用等待函数来等待所需的事件、信号,在等待的过程中,线程处于睡眠态,当接收到信号后,内核恢复线程的运行。等待函数如:WaitForSingleObject、WaitForMultipleObjects等四个。和事件有关的函数:CreateEvent、SetEvent 、PulseEvent 、ResetEvent 、OpenEvent等。
其中,CreateEvent创建一个事件对象,参数1必须为NULL,参数2指定是否手工重新设置事件对象的状态,如果为FALSE,则当等待函数接到信号并返回后此事件对象被自动置为无效,这时等待此事件对象的其他线程就不会被唤醒;如果为TRUE,则不会被置为无效,其他等待此事件对象的的线程也将被唤醒。
ResetEvent函数可以手工将事件对象置为无效。
SetEvent函数将事件对象置为有效。
OpenEvent打开已经创建的事件对象,一般用于不同进程内的线程同步。
2、线程的编程技术
1)编写线程函数,其必须有如小原型:
DWORD WINAPI MyThread(LPVOID lpvThreadParm);
注意只能有一个参数,这个函数不能由用户调用,由操作系统调用一个内部函数如StartOfThread。
2)创建线程:一个线程的主线程由操作系统自动生成,由主线程创建其他线程用CreateThread函数。
3)终止线程:某线程调用了ExitThread函数,终止自己;调用TerminateThread函数可以终止指定的线程。
4)其他函数:设定优先级SetThreadPriority、挂起线程SuspendThread、恢复线程ResumeThread。
HANDLE
WINAPI
CreateThread (
LPSECURITY_ATTRIBUTES lpsa,
//
security属性,在WinCE下须为NULL
DWORD cbStack,
//
堆栈大小,除非定义宏,否则被忽略
LPTHREAD_START_ROUTINE lpStartAddr,
//
起始地址,即C的函数指针
LPVOID lpvThreadParam,
//
自定义的传入线程参数
DWORD fdwCreate,
//
标识线程是否立即运行,默认是
LPDWORD lpIDThread
//
新线程ID
);
线程自身应用return结束,也可使用ExitThread()结束;主线程可以使用WaitForSingleObject(hThreadHandle, dwMilliseconds)等待线程结束,然后使用GetExitCode()获得返回码,最后使用CloseHandle()释放核心对象
CWinThread
*
AFXAPI AfxBeginThread(
//
创建工作者线程重载方法
AFX_THREADPROC pfnThreadProc,
//
线程起始函数
LPVOID pParam,
//
自定义参数
int
nPriority
=
THREAD_PRIORITY_NORMAL,
//
优先级
UINT nStackSize
=
0
,
//
栈大小
DWORD dwCreateFlags
=
0
,
//
标识线程是否立即运行,默认是
LPSECURITY_ATTRIBUTES lpSecurityAttrs
=
NULL
//
安全属性
);
CWinThread
*
AFXAPI AfxBeginThread( // 创建UI线程
CRuntimeClass
*
pThreadClass,
//
指定线程类,为CWinThread子类
int
nPriority
=
THREAD_PRIORITY_NORMAL,
UINT nStackSize
=
0
,
DWORD dwCreateFlags
=
0
,
LPSECURITY_ATTRIBUTES lpSecurityAttrs
=
NULL
);
CWinThread
*
pSubQuerySampleThread
=
AfxBeginThread(SubThread,(LPVOID)
this
,
0
,
0
,
0
,
0
);
pSubThread
->
SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
HANDLE hCloseEvent
=
CreateEvent(NULL,TRUE,FALSE,NULL);
if
(INVALID_HANDLE_VALUE
==
hCloseEvent) {... ...}
SetEvent(hCloseEvent);
… …
ResetEvent(hCloseEvent);
DWORD dwEvent = WaitForMultipleObjects( 3 ,signals,FALSE, - 1 );
if (WAIT_OBJECT_0 == dwEvent) {
if (WAIT_OBJECT_0 + 1 == dwEvent) {
BOOL bInitiallyOwn
=
FALSE,
//
标识初始时是否有信号
BOOL bManualReset
=
FALSE,
//
标识是否为手动置位
LPCTSTR lpszNAme
=
NULL,
//
在进程间同步是可以指定名字
LPSECURITY_ATTRIBUTES lpsaAttribute
=
NULL
//
安全标识
);
CSyncObject
*
ppObjects[],
//
同步对象数组
DWORD dwCount,
//
同步对象个数
BOOL bInitialLock
=
FALSE
//
标识初始时是否访问对象
);
//
自定义一个用于线程同步的类EventLock,并声明一些CEvent静态成员:
#define
EVNT_CNT 3
class
EventLock
{
public:
DWORD WaitForEvents();
void SetEvent(int iNum);
void ResetEvent(int iNum);
EventLock();
virtual ~EventLock();
static CEvent *pevnt[EVNT_CNT]; // EVNT_CNT标识事件对象数
private:
static CEvent evntClose, evntBegin, evntPause;
CMultiLock *pLock;
}
;
//
创建CEvent实例:
CEvent EventLock::evntClose (FALSE,TRUE);
CEvent EventLock::evntBegin (FALSE,TRUE);
CEvent EventLock::evntPause (FALSE);
//
初始化同步对象数组:
CEvent
*
EventLock::pevnt[]
=
{&evntClose,&evntBeginSample,
&evntPauseSample, &evntPreSample}
;
//
在构造器中创建CMultiLock实例:
EventLock::EventLock()
{
pLock = new CMultiLock((CSyncObject **)EventLock::pevnt,EVNT_CNT);
}
EventLock::
~
EventLock()
{
delete pLock;
}

//
与Event相同的MFC CEvent置位、复位操作:
void
EventLock::ResetEvent(
int
iNum )
{
ASSERT(0<=iNum && iNum<EVNT_CNT);
pevnt[iNum]->ResetEvent();
}
void
EventLock::SetEvent(
int
iNum)
{
ASSERT(0<=iNum && iNum<EVNT_CNT);
pevnt[iNum]->SetEvent();
}
//
使用CMultiLock::Lock()等待事件激发,此处为等待任意事件激发:
DWORD EventLock::WaitForEvents()
{
DWORD dwEvent = 0;
dwEvent = pLock->Lock(INFINITE, FALSE); // 第二个参数为TRUE则等待全部事件
dwEvent -= WAIT_OBJECT_0;
return dwEvent;
}
本文介绍了Windows CE环境下的多线程编程技术,包括线程的启动、运行状态控制、同步及数据通信等内容。详细解释了如何使用CreateThread、AfxBeginThread创建线程,以及如何通过Event对象实现线程间的同步。

277

被折叠的 条评论
为什么被折叠?



