您的位置:首页 > 其它

学习笔记——多线程

2015-07-25 19:14 197 查看
#include <Windows.h>
DWORD WINAPI
ThreadFunc(LPVOID);              //线程声明

//产生一个线程。创建成功返回handle,被称为核心对象。否则返回FLASE。 可以调用GetLastError()获知原因

//返回线程句柄 
HANDLE hThrd
= CreateThread(NULL,

                                           0,                              //线程堆栈大小。默认1MB

                                           ThreadFunc,          //线程起始地址。函数指针

                                           (LPVOID)i,              //线程函数参数

                                           0,                             //允许产生一个暂时挂起的线程。默认“立即开始执行”

                                           &threadId
);           //新线程的ID会被传回这里。类型:DWORD

 //释放核心对象。核心对象包含引用计数器,所以创建核心对象,使用完成后要释放。

//成功返回TRUE,失败返回FALSE

BOOL CloseHandle(HANDLEhObject);

//线程结束代码(exit code)。判断线程是否结束

//函数执行成功则返回TRUE,失败FALSE。线程的结束代码放在lpExitCode参数中,STILL_ACTIVE代表线程尚未结束。

BOOL GetExitCodeThread(

                                        HANDLE
hThread,                      //由CreateThread()传回的线程handle
                                        LPDWORDlpExitCode);           //指向一个DWORD,用以接收结束代码(exit code)。

 //结束一个线程。使用在一个线程函数执行流程内。相当于C runtime library中的exit()函数

VOID ExitThread(DWORDdwExitCode);              //指定此线程之结束代码

//主线程:程序启动后就执行的那个线程。

//1.必须负责GUI程序中的主消息循环。     2.这一线程结束(除ExitThread()) 会使程序中的所有线程都被迫结束,其他线程有可能没机会清理工作

 在主线程中调用 ExitThread()。会导致主线程结束 而其他线程继续存在。这么做会跳过runtime library中的清理(cleanup)函数,因而没有将已开启的文件清理掉。不推荐。

Win32说明文件一再强调线程分为GUI线程和worker线程两种。GUI线程负责建造窗口以及处理主消息循环。worker负责执行纯粹运算工作,如重新计算或重新编页等等,它们会导致主线程的消息队列失去反应。一般而言,GUI线程绝对不会去做那些不能够马上完成的工作。

GUI线程:拥有消息队列的线程。任何一个特定窗口的消息总是被产生这一窗口的线程抓到并处理。所有对此窗口的改变也都应该由该线程完成。

worker线程不能产生窗口、对话框、消息框,或任何其他与UI有关的东西。否则就会有一个消息队列产生出来并附着到此线程身上,变成GUI线程。

//等待一个线程的结束后,才继续往下执行。

//此函数成功有三个因素:

//1. 等待的目标(核心对象)变成激发状态。 返回 WAIT_OBJECT_0 。

//2. 核心对象变成激发状态之前,等待时间终了。返回 WAIT_TIMEOUT 。

//3. 如果一个拥有 mutex (互斥器)的线程结束前没有释放 mutex,则返回 WAIT_ABANDONED 。

//如果函数失败,则传回 WAIT_FAILED。调用 GetLaseError()。

DWORD WaitForSingleObject(

                            HANDLE hHandle,                      //等待对象的 handle (代表一个核心对象)。
                            DWORD dwMilliseconds);       //等待的最长时间。时间终了,即使 handle 尚未成为激发状态,此函数还是要返回。

                                                                                    0(代表立即返回),也可以 INFINITE 代表无穷等待

设定 time-out 为0,使你能够检查 handle 的状态并立即返回,没有片刻停留。

如果 handle 已经备妥,那么这个函数会成功并传回 WAIT_OBJECT_0。

否则,函数立即返回并传回 WAIT_TIMEOUT 。

WaitForSingleObject()
可以面对多种 handles 工作,不一定非要使线程。事实上,Win32 中大部分以 HANDLE 表示的对象都能够作为 WaitForSingleObject() 的等待目标。视你所拥有的对象不同,操作系统等待的事情也不一样。形式上来说,系统等待着这一对象“被激发”。

当线程正在执行时,线程对象处于未激发状态。当线程结束时,线程对象就被激发了。

//等待多个进程

//返回值:

//1. 如果因为时间终了而返回,则返回值为 WAIT_TIMEOUT

//2. 如果 bWaitAll 是 TRUE,返回值将是 WAIT_OBJECT_0

//3. 如果 bWaitAll 是 FALSE,返回值减去 WAIT_OBJECT_0,就表示数组中哪一个 handle 被激发了。

//4. 如果你等待的对象中有任何 mutexes ,那么返回值可能从 WAIT_ABANDONED_0 到 WAIT_ABANDONED_0 + nCount -1。

//5. 如果函数失败,传回 WAIT_FAILED。GetLastError()查看

DWORD WaitForMultipleObjects(

                                 DWORD nCount,               // lpHandles 中元素个数。最大容量是 MAXIMUM_WAIT_OBJECTS
                                 CONST
HANDLE *lpHandles,   // 指向由对象 handles 所组成的数组。这些 handles 不需要为相同的类型
                                 BOOL bWaitAll,                  // TRUE,表示所有 handles 都必须激发,此函数才返回。 否则,有一个激发就返回
                                 DWORD
dwMilliseconds );        
// 该时间终了,函数就返回。0,用于测试。INFINITE,表示无穷

在一个GUI程序中等待: 在“对象被激发”或“消息到达队列”时被唤醒而返回

//和
WaitForMultipleObjects 比较,返回值多了“消息到达队列”,返回值是 WAIT_OBJECT_0 + nCount

DWORD MsgWaitForMultipleObjects(

             DWORD nCount,

             LPHANDLE pHandles,

             BOOL fWaitAll,

             DWORD dwMilliseconds,

             DWORD dwWakeMask);
dwWakeMask   欲观察的用户输入消息,可以是:

           QS_ALLINPUT

           QS_HOTKEY

           QS_INPUT

           QS_KEY

           QS_MOUSE

           QS_MOUSEBUTTON

           QS_MOUSEMOVE

           QS_PAINT

           QS_POSTMESSAGE

           QS_SENDMESSAGE

           QS_TIMER

 WaitForMultipleObjects() 不允许 handles 数组中有缝隙产生。即参数中 handles 中的每个核心对象都不能为空。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: