欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

创建线程的方式

程序员文章站 2022-06-10 20:50:09
...

一、创建线程的三种方式

1. CreateTread

函数的具体格式如下:

HANDLE CreateThread(
                    LPSECURITY_ATTRIBUTES lpThreadAttributes,
                    DWORD dwStackSize,
                    LPTHREAD_START_ROUTINE lpStartAddress,
                    LPVOID lpParameter,
                    DWORD dwCreationFlags,
                    LPDWORD lpThreadID
                   );

参数说明:

参数 说明
lpThreadAttrivutes 指向SECURITY_ATTRIBUTES的指针,用于定义新线程的安全属性,一般设置成NULL
dwStackSize 分配以字节数表示的线程堆栈的大小,默认值是0
lpStartAddress 指向一个线程函数地址。每个线程都有自己的线程函数,线程函数是线程具体的执行代码
lpParameter 传递给线程函数的参数
dwCreationFlags 表示创建线程的运行状态,其中CREATE_SUSPEND表示挂起当前创建的线程,而0表示立即执行当前创建的进程
lpThreadID 返回新创建的线程的ID编号

返回值:
成功返回新线程的句柄,失败返回NULL

①线程函数
  1. 线程函数的声明
    必须是全局函数或者是静态成员函数。这里使用全局变量
DWORD WINAPI ThreadProc(LPVOID lpParam);//主要是放入线程中的函数
  1. 声明传入参数
    为了传入多个参数,这里我们一般是采用结构体的。
//为了传递多个参数,采用结构体
struct threadInfo
{
	HWND hWnd;  //窗口句柄
	....
	....
};
  1. 类中定义
protected:
	HANDLE hThread[4];//用来存储线程句柄
	DWORD dwThreadID[4];//用于存放线程的ID
	threadInfo Info[3];//用于传递线程所需要的参数
  1. 创建线程
	for (int i = 0; i < 3; i++)
	{
		hThread[i] = CreateThread(NULL, 0, ThreadProc, &Info[i], 0, &dwThreadID[i]);
		//注意不需要使用,需要释放
		CloseHandle(hThread[i]);
	}
2. AfxBeginThread

函数的具体格式如下:

//创建工作线程
CWinThread* AfxBeginThread(
      AFX_THREADPROC pfnThreadProc,
      LPVOID pParam,
      int nPriority = THREAD_PRIORITY_NORMAL,
      UINT nStackSize = 0,
      DWORD dwCreateFlags = 0,
      LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
     );
//创建用户界面
CWinThread* AfxBeginThread(
      CRuntimeClass* pThreadClass,
      int nPriority = THREAD_PRIORITY_NORMAL,
      UINT nStackSize = 0,
      DWORD dwCreateFlags = 0,
      LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
     );

参数说明:

参数 说明
pfnThreadProc 指向工作线程的控制函数。不能是NULL。这个函数必须按下面的方式定义;UINT MyControllingFunction( LPVOID pParam );
pThreadClass 从CWinThread继承的对象的RUNTIME_CLASS。
pParam 将要传送给控制函数的参数,如pfnThreadProc中定义的函数参数所示。
nPriority 设定的线程的优先级。如果为0,则使用与创建它线程相同的优先级。
nStackSize 指定新线程使用的栈的以字节为单位的大小。如果为0,则缺省的栈大小与创建它的线程的栈大小相同。
dwCreateFlags 指定控制线程的创建过程的附加标志。这个标志可以是两个值之一: ① CREATE_SUSPENDED 经过一个延迟后启动这个线程。这个线程将在调用ResumeThread 以后才会启动。 ② 0 创建后立即启动这个线程。
lpSecurityAttrs 指向一个SECURITY_ATTRIBUTES结构,它指定了线程的安全特性。如果为空,将使用与创建它的线程相同的安全特性。如果需要获得有关这个结构的详细信息

返回值:
指向新创建的线程对象的指针。

AfxBeginThread创建一个新的CWinThread对象,调用它的CreateThread函数以启动这个线程,并且返回这个线程的指针。整个过程都进行检查以保证如果创建失败,所有的对象都会被适当地释放。为了结束这个线程,可以在线程内调用AfxEndThread,或者从工作线程的控制函数内返回。

②线程函数
  1. 线程函数的声明
    必须是全局函数或者是静态成员函数。一般使用静态成员函数作为线程传入整个类对象
//定义全局
UINT MyThreadFunction(LPVOID pParam);

//类中的静态成员
protected:
static UINT MyThread(LPVOID pParam);
  1. 创建线程
for (int i = 0; i < 3; i++)
	{
		//线程函数调用主对话框类的成员:线程函数的参数起着决定性作用!
		CWinThread  *pThread = AfxBeginThread(MyThread, this);//使用this
		//CWinThread  *pThread = AfxBeginThread(MyThreadFunction, &Info[i]);
		//不需要释放
	}
	
	
//线程函数的方法
UINT CThreadDlg::MyThread(LPVOID pParam)
{
	CThreadDlg *pDlg = (CThreadDlg *)pParam;
	int tipMsg = pDlg->Info->nOffset; //访问类中的变量
	CString strTipMsg;

	while (TRUE)
	{
		strTipMsg.Format(_T("%d"), tipMsg);
		OutputDebugString(strTipMsg);//输出
		Sleep(50);
	}
	return 0;
}
系统调试信息输出的捕获工具

DebugView是一个系统调试信息输出的捕获工具。

在程序中使用如下函数:
  1> OutputDebugString 或者在MFC中使用TRACE
  2> 内核模式中使用Out_Debug_String,DbgPrint ,_Debug_Printf_Service
  
编译程序为DEBUG版本,然后运行程序(不是在vs 中运行,是单独运行),打开debugview 就可以在其中看到输出的调试信息。
DebugView 调试入门

3. _beginthreadex

待补充

二、总结

1、CreateThread,线程中不使用CRT,不使用MFC库

2、_beginthreadex,线程中使用CRT,不使用MFC库,初始化CRT后,调用CreateThread

3、AfxbeginThread,线程中使用CRT,使用MFC库,或者其中任何之一,初始化MFC后,调用_beginthreadex

MFC中线程创建的函数,首先创建了相应的CWinThread对象,然后调用CWinThread::CreateThread,在CWinThread::CreateThread中完成了对线程对象的初始化工作,然后,调用_beginthreadex创建线程。注意不要在一个MFC程序中使用_beginthreadex()或CreateThread()。