多线程程序设计之创建线程(Windows下C++实现)

来源:互联网 发布:excel数据分析占比 编辑:程序博客网 时间:2024/05/20 16:43

线程概述

理解Windows内核对象

线程是系统内核对象之一。在学习线程之前,应先了解一下内核对象。内核对象是系统内核分配的一个内存块,该内存块描述的是一个数据结构,其成员负责维护对象的各种信息。内核对象的数据只能由系统内核来访问,应用程序无法在内存中找到这些数据结构并直接改变他们的内容。

常用的系统内核对象有事件对象、文件对象、作业对象、互斥对象、管道对象、进程对象和线程对象等。不同类型的内核对象,其数据结构各有不同。

理解进程和线程

进程被认为是一个正在运行的程序的实例,它也属于系统内核对象。可以将进程简单的理解为一个容器,它只是提供空间,执行程序的代码是由线程来实现的。线程存在于进程中,它负责执行进程地址空间中的代码。当一个进程创建时,系统会自动为其创建一个线程,该线程被称为主线程。在主线程中用户可以通过代码创建其他线程,当进程中的主线程结束时,进程也就结束了。

线程的创建

Windows下,创建线程有多种方式,以下将逐一介绍。注意它们的区别。

使用CreateThread函数创建线程

Windows API函数。该函数在主线程的基础上创建一个新线程。微软在Windows API中提供了建立新的线程的函数CreateThread。

HANDLECreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,//线程安全属性DWORD dwStackSize,//堆栈大小LPTHREAD_START_ROUTINE lpStartAddress,//线程函数LPVOID lpParameter,//线程参数DWORD dwCreationFlags,//线程创建属性LPDWORD lpThreadId//线程ID);

代码示例如下:

#include "stdafx.h"#include<iostream>#include<Windows.h>using namespace std;DWORD WINAPI Fun1Proc(LPVOID lpParameter){    cout << "thread function Fun1Proc!\n";    return 0;}int main(){    HANDLE hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);    CloseHandle(hThread1);    Sleep(1000);    cout << "main end!\n";    system("pause");    return 0;}

运行结果:
这里写图片描述

使用_beginthreadex函数创建线程

除了使用CreateThread API函数创建线程外,还可以用C++语言提供的_beginthreadex函数来创建线程。

uintptr_t _beginthreadex( // NATIVE CODE     void *security,  //线程安全属性   unsigned stack_size,  //线程的栈大小   unsigned ( *start_address )( void * ),//线程函数     void *arglist,  //传递到线程函数中的参数   unsigned initflag,  //线程初始化标记   unsigned *thrdaddr   //线程ID); 

代码示例:

#include "stdafx.h"#include<iostream>#include<Windows.h>#include<process.h>using namespace std;unsigned int _stdcall ThreadProc(LPVOID lpParameter){    cout << "thread function ThreadProc!\n";    return 0;}int main(){    _beginthreadex(NULL, 0, ThreadProc, 0, 0, NULL);    Sleep(1000);    cout << "main end!\n";    system("pause");    return 0;}

使用AfxBeginThread函数创建线程

在MFC应用程序中,还可以使用AfxBeginThread函数创建一个线程。MFC提供了两个重载版的AfxBeginThread,一个用于用户界面线程,另一个用于工作者线程。这里只讲工作者线程。

CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,  LPVOID lParam,  int nPriority = THREAD_PRIORITY_NORMAL,  UINT nStackSize = 0,  DWORD dwCreateFlags = 0,  LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL  );//用于创建工作者线程

返回值: 成功时返回一个指向新线程的线程对象的指针,否则NULL。
pfnThreadProc : 线程的入口函数,声明一定要如下: UINT MyThreadFunction(LPVOID pParam),不能设置为NULL;
pParam : 传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程.
nPriority : 线程的优先级,一般设置为 0 .让它和主线程具有共同的优先级.
nStackSize : 指定新创建的线程的栈的大小.如果为 0,新创建的线程具有和主线程一样的大小的栈
dwCreateFlags : 指定创建线程以后,线程有怎么样的标志.可以指定两个值:

  • CREATE_SUSPENDED : 线程创建以后,会处于挂起状态,直到调用ResumeThread
  • 0 : 创建线程后就开始运行。

lpSecurityAttrs : 指向一个 SECURITY_ATTRIBUTES 的结构体,用它来标志新创建线程的安全性。如果为 NULL,那么新创建的线程就具有和主线程一样的安全性。

代码略。

其他方式

创建线程还可以用boost线程库创建,也可以用c++11新标准中的线程库(std::thread)创建线程。建议采用c++11中的线程库创建线程,极为方便。且跨平台,是语言层面的。后面会学习到c++11线程库的使用。

原创粉丝点击