博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
windows多线程编程
阅读量:4610 次
发布时间:2019-06-09

本文共 3498 字,大约阅读时间需要 11 分钟。

当进程结束后所有线程都终止。多线程编程最大的问题在于共享数据的访问控制。

直接用Win32 API进行编程有很多优点:基于Win32的应用程序执行代码小,运行效率高。但是它要求程序员编写的代码较多,且需要管理所有系统提供给程序的资源。

▶ 创建线程

HANDLE CreateThread(      

LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD     
SIZE_T dwStackSize,                                    // initial stack size     
LPTHREAD_START_ROUTINE lpStartAddress,    // thread function     
LPVOID lpParameter,                                    // thread argument     
DWORD dwCreationFlags,                            // creation option     
LPDWORD lpThreadId                                 // thread identifier   
);    
 线程函数原型:DWORD WINAPI Fun(LPVOID lpParamter);
 参数说明:
lpThreadAttributes :NULL使用默认安全性,不可以被子线程继承,否则需要定义一个结构体将它的bInheritHandle成员初始化为TRUE。
dwStackSize:设置初始栈的大小,以字节为单位,如果为0,那么默认将使用与调用该函数的线程相同的栈空间大小。任何情况下,Windows根据需要动态延长堆栈的大小。
lpStartAddress:指向线程函数的指针,形式:@函数名,函数名称没有限制,但是必须以下列形式声明:DWORD WINAPI ThreadProc (LPVOID lpParam) ,格式不正确将无法调用成功。但lpStartAddress要这样通过LPTHREAD_START_ROUTINE转换如:(LPTHREAD_START_ROUTINE)MyVoid。MyVoid声明为 void MyVoid();
lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为NULL。
dwCreationFlags:可取如下标志
1. CREATE_SUSPENDED(0x00000004):创建一个挂起的线程
2. 0:表示创建后立即激活
3. STACK_SIZE_PARAM_IS_A_RESERVATION(0x00010000):dwStackSize参数指定初始的保留堆栈的大小,否则,dwStackSize指定提交的大小。该标记值在Windows 2000/NT and Windows Me/98/95上不支持。
lpThreadId:保存新线程的id。
返回值:
如果CreateThread成功,传回一个handle,代表新线程。否则传回一个FALSE。如果失败,你可以调用GetLastError()获知原因。
必须指定的参数是lpStartAddress,其它的都可以用默认值0或NULL。

 

 恢复/挂起线程

DWORD WINAPI ResumeThread( __in HANDLE hThread);

调用该函数可以激活一个挂起的线程。
这个函数和SuspendThread相对应。创建线程是可以创建挂起的线程
(dwCreationFlags参数指定),挂起的线程直到调用ResumeThread才开始执行。

 设置线程优先级

BOOL SetThreadPriority(
  HANDLE hThread, // handle to the thread
  int nPriority     // thread priority level
);
 nPriority 优先级别参数 可设置为以下参数
THREAD_PRIORITY_ABOVE_NORMAL 为比一般优先级高一个等级
THREAD_PRIORITY_BELOW_NORMAL 比一般低一个等级
THREAD_PRIORITY_HIGHEST   比一般高2个等级
THREAD_PRIORITY_IDLE
THREAD_PRIORITY_LOWEST    比一般低2个等级
THREAD_PRIORITY_NORMAL   一般等级
THREAD_PRIORITY_TIME_CRITICAL

 终止线程

 线程内终止

如果某线程调用了ExitThread函数就可以终止它自己。
VOID ExitThread(DWORD dwExitCode);
dwExitCode: 指定线程的推出码。
 线程外终止
BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode);
作用: 
在线程外终止一个线程,用于强制终止线程。 
参数说明: 
HANDLE htread:被终止的线程的句柄,为CWinThread指针。 
DWORD dwExitCode:退出码。

 关闭句柄

在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。

但是这个handle并不能完全代表这个线程,它仅仅是线程的一个“标识”,系统和用户可以利用它对相应的线程进行必要的操纵。如果在线程成功创建后,不再需要用到这个句柄,就可以在创建成功后,线程退出前直接CloseHandle掉,但这并不会影响到线程的运行。

不执行CloseHandle() 带来的后果:

若在线程执行完之后,没有通过CloseHandle()将引用计数减1,在进程执行期间,将会造成内核对象的泄露,相当与句柄泄露,但不同于内存泄露, 这势必会对系统的效率带来一定程度上的负面影响。但是,请记住,当进程结束退出后,系统仍然会自动帮你清理这些资源。但是在这里不推荐这种做法,毕竟不是 一个良好的编程习惯!
( 应用程序运行时,有可能泄露内核对象,但是当进程终止运行时,系统能确保所有内容均被正确地清除。另外,这个情况是用于所有对象,资源和内存块,也就是说,当进程终止时,系统将保证不会留下任何对象。)

▶ 判断程序运行状态

线程结束代码可以藉由调用GetExitCodeThread()而得知。
BOOL GetExitCodeThread( HANDLE hThread, LPDWORD lpExitCode);

 同步与互斥

Win32 API提供了一组能是线程阻塞自身执行的等待函数。这些等待函数在其参数中的一个或多个同步对象产生了信号,或者超过规定的等待时间才会返回。在等待未返回时,线程处于等待状态,此时线程只消耗很少的CPU。

最常用的等待函数是:
DWORD WINAPI WaitForSingleObject(
  __in HANDLE hHandle,
  __in DWORD dwMilliseconds
);
 参数:
hHandle: 对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。
当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
dwMilliseconds: 定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle 标记的对象被触发,或者时间到了。如果dwMilliseconds 为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds 为INFINITE,对象被触发信号后,函数才会返回。

返回值:

WAIT_ABANDONED 0x00000080:当hHandle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值。
  WAIT_OBJECT_ 0  0x00000000 :核心对象已被激活
  WAIT_TIMEOUT  0x00000102:等待超时
WAIT_FAILED    0xFFFFFFFF :出现错误,可通过GetLastError得到错误代码

 

转载于:https://www.cnblogs.com/shockerjue/archive/2012/12/28/2837654.html

你可能感兴趣的文章
Python 和其他编程语言数据类型的比较
查看>>
T2695 桶哥的问题——送桶 题解
查看>>
HTML5 表单
查看>>
Android群英传》读书笔记 (3) 第六章 Android绘图机制与处理技巧 + 第七章 Android动画机制与使用技巧...
查看>>
关于微信公众平台测试号配置失败的问题
查看>>
【NOIP2001】统计单词个数
查看>>
linux常用端口
查看>>
异常处理
查看>>
/proc/uptime详解
查看>>
如何建立合适的索引?
查看>>
acwing 651. 逛画展
查看>>
(待完成)qbxt2019.05 总结12 - 趣味题目 鹰蛋
查看>>
[2018/11/18] Java数据结构(2) 简单排序 冒泡排序 选择排序 插入排序
查看>>
关于WPF程序只运行一个实例的方法
查看>>
图论:点分治
查看>>
mysql
查看>>
C/C++ 知识点---sizeof使用规则及陷阱分析(网摘)
查看>>
前端开发在线小工具
查看>>
Hadoop 使用Combiner提高Map/Reduce程序效率
查看>>
前言 转录组
查看>>