断断续续搞了好几天的Windows下多线程编程,现将一点总结写出来,供大家参考:
一、什么是进程和线程
进程和线程的区别:
进程主要包括:(1)私有虚拟地址空间(2)可执行程序(代码和数据)(3)打开系统资源列表句柄(4)进程ID(5)安全访问标志(6)至少一个执行线程
线程主要包括:(1)一组Cpu寄存器状态(2)两个堆栈(系统态和用户态)(3)线程局部存储区域TLS(4)线程ID(5)安全特性
进程是不活泼的,不执行任何东西,它是线程的容器
进程、模块和线程的关系:
模块是一段可执行程序代码、其代码、资源等被载入系统中,由系统创建一个结构体(MDB)来管理它。进程中包括虚拟地址空间、一系列模块组和线程组成,线程主要是执行模块中的可执行代码。
二、Windows多线程编程之创建线程
注意事项:
(1) 如果有共享变量,则一定要声明为volatile类型,比如多线程并发的控制变量
(2) 声明生成线程后的线程句柄HANDLEhThread和所创建线程的生成的线程id DWORD ThreadId
(3) 编写线程函数 ThreadFunc(…)
hThread=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFunc,
NULL,
0,
&ThreadID);
函数原型为HANDLE CreateThread(LPSECURITY_ATTRIBUTESlpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:
" lpThreadAttributes:指向一个 SECURITY_ATTRIBUTES结构的指针,该结构决定了线程的安全属性,一般置为 NULL;
" dwStackSize:指定了线程的堆栈深度,一般都设置为0;
" lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址。一般情况为(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc是线程函数名;
" lpParameter:指定了线程执行时传送给线程的32位参数,即线程函数的参数;
" dwCreationFlags:控制线程创建的附加标志,可以取两种值。如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数ResumeThread被调用;
" lpThreadId:该参数返回所创建线程的ID;
" 如果创建成功则返回线程的句柄,否则返回NULL。
几个常用的Windows多线程函数:
DWORD SuspendThread(HANDLE thread),该函数用于挂起指定的线程
DWORD ResumeThread(HANDLE thread)用于结束线程的挂起状态
VOID ExitThread(DWORDdwExitCode);在线程执行函数中被调用,用于线程终结自身,参数dwExitCode用于设置函数的退出码
Void TerminateThread(HANDLE hThread,DWORDdwExitCode),强制退出,设置函数的退出码
BOOL PostThreadMessage(DWORD threaded,UINT Msg,WPARAMwParam,LPARAM lParam)
该函数将一条消息放入指定的线程消息队列中,立即返回。如果该线程没有创建消息循环,则该函数执行失败。
DWORD WaitForSingleObject(HANDLE hHandle,DWORDdwMilliseconds);
三、 MFC下创建线程
MFC中分为两类线程,一类是用户界面线程,另一类是工作者线程,两类的区别就是有无消息循环机制。
MFC中一般用CWindThread*AfxBegineThread()来创建并初始化一个线程的运行,该函数有两种重载形式,分别用于创建工作者线程和界面线程
(1)CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, nPriority,UINT nStackSize, DWORDdwCreateFlags=0, LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
pfnThreadProc执行工作者线程的执行函数指针,线程函数必须声明如下:UINTExecutingFunction(LPVOID pParam);
" pParam:传递给线程函数的一个32位参数,执行函数将用某种方式解释该值。它可以是数值,或是指向一个结构的指针,甚至可以被忽略;
" nPriority:线程的优先级。如果为0,则线程与其父线程具有相同的优先级;
" nStackSize:线程为自己分配堆栈的大小,其单位为字节。如果nStackSize被设为0,则线程的堆栈被设置成与父线程堆栈相同大小;
" dwCreateFlags:如果为0,则线程在创建后立刻开始执行。如果为CREATE_SUSPEND,则线程在创建后立刻被挂起;
" lpSecurityAttrs:线程的安全属性指针,一般为NULL;
(2)界面线程:在界面线程中AfxBegineThread参数中线程函数和参数不同,其他都一样
CWinThread* AfxBeginThread(CRuntimeClass*pThreadClass,
int nPriority=THREAD_PRIORITY_NORMAL,
UINT nStackSize=0,
DWORD dwCreateFlags=0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
在界面线程中,重载Inistance()和Existence()来初始化和界面和当界面退出时进行保存的工作
四、 多线程之间的通讯
i. 使用全局变量,用volatile进行修饰
ii. 使用自定义消息进行通讯
注意事项:
(1) 自定消息要在WM_USER值之上定义
(2) 线程之间传递消息要用PostThreadMessage();
(3) 在消息影射表中进行影射:如果是主线程用ON_MESSAGE(),普通线程用ON_THREAD_MESSAGE(WM_MESSAGE,fun);
(4) 定义消息处理函数:如果是普通线程处理函数,前面要加上afx_msgLONG fun(UINT wParam, LONG lParam)
(5) 实现的时候,前面一定要加上类名,否则会出现连接错误LONGCLASSNAME::fun();
(6) 线程一定要有自己的消息对列才可以接收消息,vc中从CWinThread中继承的,都有消息队列
欢迎您使用http://Blogmove.cn提供的"博客搬家"和"博文三窟"服务.
一、什么是进程和线程
进程和线程的区别:
进程主要包括:(1)私有虚拟地址空间(2)可执行程序(代码和数据)(3)打开系统资源列表句柄(4)进程ID(5)安全访问标志(6)至少一个执行线程
线程主要包括:(1)一组Cpu寄存器状态(2)两个堆栈(系统态和用户态)(3)线程局部存储区域TLS(4)线程ID(5)安全特性
进程是不活泼的,不执行任何东西,它是线程的容器
进程、模块和线程的关系:
模块是一段可执行程序代码、其代码、资源等被载入系统中,由系统创建一个结构体(MDB)来管理它。进程中包括虚拟地址空间、一系列模块组和线程组成,线程主要是执行模块中的可执行代码。
二、Windows多线程编程之创建线程
注意事项:
(1) 如果有共享变量,则一定要声明为volatile类型,比如多线程并发的控制变量
(2) 声明生成线程后的线程句柄HANDLEhThread和所创建线程的生成的线程id DWORD ThreadId
(3) 编写线程函数 ThreadFunc(…)
hThread=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFunc,
NULL,
0,
&ThreadID);
函数原型为HANDLE CreateThread(LPSECURITY_ATTRIBUTESlpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:
" lpThreadAttributes:指向一个 SECURITY_ATTRIBUTES结构的指针,该结构决定了线程的安全属性,一般置为 NULL;
" dwStackSize:指定了线程的堆栈深度,一般都设置为0;
" lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址。一般情况为(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc是线程函数名;
" lpParameter:指定了线程执行时传送给线程的32位参数,即线程函数的参数;
" dwCreationFlags:控制线程创建的附加标志,可以取两种值。如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数ResumeThread被调用;
" lpThreadId:该参数返回所创建线程的ID;
" 如果创建成功则返回线程的句柄,否则返回NULL。
几个常用的Windows多线程函数:
DWORD SuspendThread(HANDLE thread),该函数用于挂起指定的线程
DWORD ResumeThread(HANDLE thread)用于结束线程的挂起状态
VOID ExitThread(DWORDdwExitCode);在线程执行函数中被调用,用于线程终结自身,参数dwExitCode用于设置函数的退出码
Void TerminateThread(HANDLE hThread,DWORDdwExitCode),强制退出,设置函数的退出码
BOOL PostThreadMessage(DWORD threaded,UINT Msg,WPARAMwParam,LPARAM lParam)
该函数将一条消息放入指定的线程消息队列中,立即返回。如果该线程没有创建消息循环,则该函数执行失败。
DWORD WaitForSingleObject(HANDLE hHandle,DWORDdwMilliseconds);
三、 MFC下创建线程
MFC中分为两类线程,一类是用户界面线程,另一类是工作者线程,两类的区别就是有无消息循环机制。
MFC中一般用CWindThread*AfxBegineThread()来创建并初始化一个线程的运行,该函数有两种重载形式,分别用于创建工作者线程和界面线程
(1)CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, nPriority,UINT nStackSize, DWORDdwCreateFlags=0, LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
pfnThreadProc执行工作者线程的执行函数指针,线程函数必须声明如下:UINTExecutingFunction(LPVOID pParam);
" pParam:传递给线程函数的一个32位参数,执行函数将用某种方式解释该值。它可以是数值,或是指向一个结构的指针,甚至可以被忽略;
" nPriority:线程的优先级。如果为0,则线程与其父线程具有相同的优先级;
" nStackSize:线程为自己分配堆栈的大小,其单位为字节。如果nStackSize被设为0,则线程的堆栈被设置成与父线程堆栈相同大小;
" dwCreateFlags:如果为0,则线程在创建后立刻开始执行。如果为CREATE_SUSPEND,则线程在创建后立刻被挂起;
" lpSecurityAttrs:线程的安全属性指针,一般为NULL;
(2)界面线程:在界面线程中AfxBegineThread参数中线程函数和参数不同,其他都一样
CWinThread* AfxBeginThread(CRuntimeClass*pThreadClass,
int nPriority=THREAD_PRIORITY_NORMAL,
UINT nStackSize=0,
DWORD dwCreateFlags=0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
在界面线程中,重载Inistance()和Existence()来初始化和界面和当界面退出时进行保存的工作
四、 多线程之间的通讯
i. 使用全局变量,用volatile进行修饰
ii. 使用自定义消息进行通讯
注意事项:
(1) 自定消息要在WM_USER值之上定义
(2) 线程之间传递消息要用PostThreadMessage();
(3) 在消息影射表中进行影射:如果是主线程用ON_MESSAGE(),普通线程用ON_THREAD_MESSAGE(WM_MESSAGE,fun);
(4) 定义消息处理函数:如果是普通线程处理函数,前面要加上afx_msgLONG fun(UINT wParam, LONG lParam)
(5) 实现的时候,前面一定要加上类名,否则会出现连接错误LONGCLASSNAME::fun();
(6) 线程一定要有自己的消息对列才可以接收消息,vc中从CWinThread中继承的,都有消息队列
欢迎您使用http://Blogmove.cn提供的"博客搬家"和"博文三窟"服务.
本文介绍了Windows多线程编程的基本概念,包括进程与线程的区别,详细讲解了如何创建线程,以及MFC中创建用户界面线程和工作者线程的方法。还提到了线程间通信的方式,如全局变量和自定义消息,并强调了线程安全的注意事项。
6347

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



