多线程编程1-入门

常用的多线程API函数(转自http://blog.csdn.net/hcqi2004/article/details/3534853)

CreateThread函数:

HANDLE CreateThread(

  LPSECURITY_ATTRIBUTES lpThreadAttributes,

  DWORD dwStackSize,

  LPTHREAD_START_ROUTINE lpStartAddress,

  LPVOID lpParameter,

  DWORD dwCreationFlags,

  LPDWORD lpThreadId);

 

参数

lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL,表示使用缺省值。

dwStackSize,线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈的大小。

lpStartAddress,指向线程函数的指针,形式:@函数名,格式不正确将无法调用成功。

  线程函数的格式:DWORD  WINAPI Threadfnc(LPVOID N); 说明:返回值必须为DWORD,必须使用WINAPI,函数名称Threadfnc可以自己随便命名,函数的参数必须是LPVOID类型。

lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为Nil。

dwCreationFlags :线程标志,可取值如下 
  CREATE_SUSPENDED 创建一个挂起的线程; 
  0 创建后立即激活。

lpThreadId:保存新线程的id。线程id是一个全局变量,唯一的表示系统任一进程中的某个线程。但不能根据id获得其handle。

 

返回值:

函数成功,返回线程句柄;函数失败返回false。

 

函数说明:

创建一个线程。

 

 

一般并不推荐使用 CreateTheard函数,而推荐使用RTL 库里的System单元中定义的 BeginTheard函数,因为这除了能创建一个线程和一个入口函数以外,还增加了几项保护措施。

 

CloseHandle函数

BOOL  CloseHandle(

HANDLE    hObject

);

参数  

    hObject : 代表一个已打开对象handle

返回值

        TRUE:执行成功,

FALSE:执行失败,可以调用GetLastError()获知失败原因。

 函数说明:

关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。

  若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成内核对象的泄露,相当于句柄泄露,但不同于内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。

 

 

GetExitCodeThread函数:

功能: 获取一个结束线程的返回值

BOOL   GetExitCodeThread (

HANDLE  hThread,

 LPDWORD  lpExitCode

);

参数:

hThread: 线程对象的句柄

        lpExitCode: 用于存储线程的返回值,如果线程结束,那么线程的结束代码会被放在lpExitCode参数中;如果线程尚未结束,lpExitCode的值是STILL_ACTIVE.

返回值:

函数执行成功则返回非0值,否则返回 0(FALSE)。

函数说明:

   获取线程结束的返回值。

 

 

ExitThread 函数

VOID ExitThread(DWORD dwExitCode);

参数

dwExitCode: 线程的结束代码

返回值

  无返回值.

说明

该函数最好用于 C 程序里,在 C++里,return 前会调用析构函数,调用该函数结束线程,并不会调用有关对象的析构函数以及其它的自动清理动作.当在线程里调用该函数后,线程的堆栈将被收回,所有未完成的I/O操作将被取消,于其连接的动态连接库也被分离.

当调用线程的函数返回后,线程自动终止。如果需要在线程的执行过程中终止则可调用该函数。

WaitForSingleObject函数

DWORD WaitForSingleObject(

  HANDLE hHandle,

  DWORD dwMilliseconds

);

参数

hHandle:事件的句柄,在此指线程句柄;

dwMilliseconds:等待的最长时间。时间到了如果hHandle没有返回,函数还是要返回的;如果时间是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT;

此值为0,代表立刻返回

此值为INFINITE,代表无穷等待。

 

返回值

WAIT_OBJECT_0:函数成功返回,在规定时间内检测到信号状态

WAIT_FAILED:函数失败,可调用GetLastError()查看更多消息

WAIT_TIMEOUT:等待时间到了,还没有检测到信号状态

WAIT_ABANDONED:拥有mutex(互斥器)的线程结束前没有释放mutex

 

函数说明:

设即将等待的线程为线程#1,正在执行的线程为线程#2,调用WaitForSingleObject,设定该函数的第一个参数是线程#2的句柄,则线程#1开始睡眠,直到线程#2结束为止。

创建多个线程,线程并不一定是按照创建的先后顺序结束的。调用该函数只能监测指定的一个线程。

WaitForMultipleObject函数

DWORD WaitForMultipleObjects(

  DWORD nCount,

  const HANDLE* lpHandles,

  BOOL bWaitAll,

  DWORD dwMilliseconds

  );

参数

nCount:表示lpHandles所指句柄数据的元素个数,

最大容量是MAXIMUM_WAIT_OBJECTS

lpHandles:指向对象句柄数组的指针

bWaitAll:是否等待所有对象都有信号

此值为false,返回值减去WAIT_OBJECT_0 就是参数lpHandles数组的序号。如果同时有多个内核对象被出发,这个函数返回的只是其中序号最小的那个。

此值为true,

返回值为WAIT_OBJECT_0,表示所有的事件都被设置了   .  

          返回值为WAIT_ABANDONED_0到(WAIT_ABANDONED_0+ nCount–1) ,表示有一个事件被丢弃

 

dwMilliseconds:等待的最长时间。时间到了如果hHandle没有返回,函数还是要返回的;如果在规定那个时间内有信号状态则返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但事件还是无信号状态则返回WAIT_TIMEOUT;

此值为0,代表立刻返回

此值为INFINITE,代表无穷等待。

 

返回值

WAIT_OBJECT_0:函数成功返回,在规定时间内检测到信号状态

WAIT_FAILED:函数失败,可调用GetLastError()查看更多消息

WAIT_TIMEOUT:等待时间到了,还没有检测到信号状态

WAIT_ABANDONED:拥有mutex(互斥器)的线程结束前没有释放mutex

 

函数说明:

多个内核对象被触发时,WaitForMultipleObjects选择其中序号最小的返回。而WaitForMultipleObjects它只会改变使它返回的那个内核对象的状态。这儿又会产生一个问题,如果序号最小的那个对象频繁被触发,那么序号比它大的内核对象将的不到被出理的机会。

lpHandles数组中不允许有缝隙产生,当某个handle被激发了,你应该在下一次调用WaitForMultipleObjects函数之前将该handle从lpHandles数组中移除。

Windows消息循环

Windows程序中的标准消息循环看起来想这个样子:

while( GetMessage(&Msg,NULL,0,0) )

{

TranslateMessage(&Msg);

DispatchMessage(&Msg);

}

调用getMessage(),除非有一个消息真正进入消息列队中,否则它不会返回。在此期间,Windows就可以自由的将cpu时间给予其他程序。

 常常回到主消息循环是十分重要的事,如果你没有这么做,你的窗口就会停止重绘,就会出现一些用户不喜欢的事情。在你使用WaitForSingleObject或者WaitForMultipleObjects函数时,它在等待某个对象被激发时,你根本没有办法回到主消息循环中去。

  为了解决这个问题,主消息循环必须修改,使它可以同时等待消息或者是核心对象被激发,你必须使用MsgWaitForMultipleObjects函数。

 

MsgWaitForMultipleObjects函数

DWORD   MsgWaitForMultipleObjects ( 
   DWORD   nCount, 
   LPHANDLE   pHandles, 
   BOOL  fWaitAll, 
   DWORD  dwMilliseconds, 
   DWORD  dwWakeMask 
);

参数

nCount:列表中的句柄数量

pHandles:指向对象句柄数组的指针

fWaitAll:是否等待所有对象都有信号,

dwMilliseconds:等待的最长时间。时间到了如果hHandle没有返回,函数还是要返回的;如果时间是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT;

此值为0,代表立刻返回

此值为INFINITE,代表无穷等待。

dwWakeMask :指定哪些消息是观察对象(欲观察的用户输入消息),可以是:

  QS_ALLINPUT

  QS_HOTKEY

QS_INPUT

QS_KEY

QS_MOUSE

QS_MOUSEBUTTON

QS_MOUSEMOVE

QS_PAINT

QS_POSTMESSAGE

QS_SENDMESSAGE

QS_TIMER

 

返回值

WAIT_OBJECT_0:函数成功返回,在规定时间内检测到信号状态

WAIT_FAILED:函数失败,可调用GetLastError()查看更多消息

WAIT_TIMEOUT:等待时间到了,还没有检测到信号状态

WAIT_ABANDONED:拥有mutex(互斥器)的线程结束前没有释放mutex

  WAIT_TO_COMPLETION:(仅适用于WaitForSingleObjectEx),由于一个I/O完成操作已准备好执行,从而造成了函数的返回。

  WAIT_OBJECT_0 + nCount:接受到由dwWakeMask指定的消息

 

函数说明:

迭代等待指定线程中的特定消息,其实这个函数就是专为等待消息而定义的。

MsgWaitForMultipleObjects函数不允许句柄数组中有缝隙产生,所以当某个句柄被激发了,你应该在下一次调用MsgWaitForMultipleObjects之前先把句柄数组做个整理、压缩

 

 

TerminateThread函数

BOOL TerminateThread(

HANDLE  hThread,

DWORD  dwExitCode

);
参数

hThread:线程的句柄

dwExitCode:线程的结束代码

 

返回值

True:函数成功

False:函数失败

 

函数说明:

如果在线程的外面终止线程,则可调用该函数。该函数执行后,线程handle将变成激发状态,并且传回结束代码。

TerminateThread函数是一个危险的函数,应该最不得已的情况下才使用。此函数一旦成功执行,指定的线程会立刻终止执行,那么可能有很多的结束处理工作还没来得及进行,线程的堆栈没有被释放,于是可能会引起内存泄漏- - -,但是此线程加载的DLL也没有机会被通知结束执行。

 

SuspendThread函数

DWORD  SuspendThread(

HANDLE hThread   //线程的句柄

);

返回值

函数成功,返回线程的前一个暂停计数或者说是前一个挂起次数,否则返回0x FFFFFFFF

 

函数说明:

挂起线程。一个线程可以被挂起多次。如果一个线程被挂起n次,则该线程也必须被恢复n次才可能得以执行。。

 

ResumeThread函数

DWORD  ResumeThread(

HANDLE hThread  //线程的句柄

);

返回值

函数成功,返回线程目前的挂起次数,否则返回0x FFFFFFFF

函数说明:

唤醒线程。

 

句柄,是整个Windows编程的基础。一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类对象中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。应用程序能够通过句柄访问相应的对象的信息,但是句柄不是一个指针程序不能利用句柄来直接阅读文件中的信息。如果句柄不在I/O文件中,它是毫无用处的。 句柄是Windows用来标志应用程序中建立的或是使用的唯一整数,Windows使用了大量的句柄来标识很多对象。

Sleep函数编辑

函数名: Sleep
功 能: 执行 挂起一段 时间
用 法: void Sleep(DWORD dwMilliseconds);
在VC中使用带上头文件
#include <windows.h>
( Sleep函数存放头文件:WinBase.h)
在gcc 编译器中,使用的头文件因gcc版本的不同而不同
#include <unistd.h>
Sleep()单位为毫秒,sleep()单位为秒(如果需要更精确可以用usleep单位为微秒)
返回值
若进程/线程挂起到参数所指定的时间则返回0,若有信号中断则返回剩余秒数。
 

下面创建一个简单的线程例子

#include<iostream>

#include<Windows.h>

using namespace std;



//线程函数

DWORD WINAPI Fun1proc(

	LPVOID lpparameter//向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为NULL

);



//main函数为主线程的入口函数地址

void main()

{

	HANDLE hThread1;

	hThread1=CreateThread(NULL//第一个参数为NULL,设置为默认的安全性

		                  ,0//第二个参数让新线程与调用线程采用一样的栈大小

						  ,Fun1proc//第三个参数指定线程1的入口函数地址

						  ,NULL//第四个参数是传递给线程1的参数

						  ,0//第五个参数设置为0让线程一旦创建就立即执行

						  ,NULL//第六个参数新线程的ID

						  );

	CloseHandle(hThread1);//关闭新线程的句柄(这里没有终止创建的新线程,只是说主线程对它的引用不感兴趣)

	

	cout<<"main thread is running"<<endl;

	Sleep(5000);

	//system("pause");

}



//线程1的入口函数

DWORD WINAPI Fun1proc( LPVOID lpparameter)

{

	cout<<"thread1 is running!!!"<<endl;

	return 0;

}

  

 

你可能感兴趣的:(多线程)