多线程编程:[2]认识CreateThread函数

操作方法

  • 01

    function CreateThread(  lpThreadAttributes: Pointer;           {安全设置}  dwStackSize: DWORD;                    {堆栈大小}  lpStartAddress: TFNThreadStartRoutine; {入口函数}  lpParameter: Pointer;                  {函数参数}  dwCreationFlags: DWORD;                {启动选项}var lpThreadId: DWORD                  {输出线程 ID }): THandle; stdcall;                     {返回线程句柄}-------------------------------------------------------------------------------- 在 Windows 上建立一个线程, 离不开 CreateThread 函数;TThread.Create 就是先调用了 BeginThread (Delphi 自定义的), BeginThread 又调用的 CreateThread.既然有建立, 就该有释放, CreateThread 对应的释放函数是: ExitThread, 譬如下面代码:-------------------------------------------------------------------------------- procedure TForm1.Button1Click(Sender: TObject);begin  ExitThread(0); {此句即可退出当前程序, 但不建议这样使用}end;-------------------------------------------------------------------------------- 代码注释: 当前程序是一个进程, 进程只是一个工作环境, 线程是工作者;每个进程都会有一个启动线程(或叫主线程), 也就是说: 我们之前大量的编码都是写给这个主线程的;上面的 ExitThread(0); 就是退出这个主线程;系统不允许一个没有线程的进程存在, 所以程序就退出了.另外: ExitThread 函数的参数是一个退出码, 这个退出码是给之后的其他函数用的, 这里随便给个无符号整数即可. 或许你会说: 这个 ExitThread 挺好用的; 其实不管是用 API 还是用 TThread 类写多线程, 我们很少用到它; 因为:1、假如直接使用 API 的 CreateThread, 它执行完入口函数后会自动退出, 无需 ExitThread;2、用 TThread 类建立的线程又绝不能使用 ExitThread 退出; 因为使用 TThread 建立线程时会同时分配更多资源(譬如你自定义的成员、还有它的祖先类(TObject)分配的资源等等), 如果用 ExitThread 给草草退出了, 这些资源将得不到释放而导致内存泄露. 尽管 Delphi 提供了 EndThread(其内部调用 ExitThread), 这也不需要我们手动操作(假如非要手动操作也是件很麻烦的事情, 因为很多时候你不知道线程是什么时候执行完毕的). -------------------------------------------------------------------------------- 除了 CreateThread, 还有一个 CreateRemoteThread, 可在其他进程中建立线程, 这不应该是现在学习的重点;现在先集中精力把 CreateThread 的参数搞彻底. 倒着来吧, 先谈谈 CreateThread 将要返回的 "线程句柄". "句柄" 类似指针, 但通过指针可读写对象, 通过句柄只是使用对象;有句柄的对象一般都是系统级别的对象(或叫内核对象); 之所以给我们的是句柄而不是指针, 目的只有一个: "安全"; 貌似通过句柄能做很多事情, 但一般把句柄提交到某个函数(一般是系统函数)后, 我们也就到此为止很难了解更多了; 事实上是系统并不相信我们. 不管是指针还是句柄, 都不过是内存中的一小块数据(一般用结构描述), 微软并没有公开句柄的结构细节, 猜一下它应该包括: 真实的指针地址、访问权限设置、引用计数等等. 既然 CreateThread 可以返回一个句柄, 说明线程属于 "内核对象".实际上不管线程属于哪个进程, 它们在系统的怀抱中是平等的; 在优先级(后面详谈)相同的情况下, 系统会在相同的时间间隔内来运行一下每个线程, 不过这个间隔很小很小, 以至于让我们误以为程序是在不间断地运行. 这时你应该有一个疑问: 系统在去执行其他线程的时候, 是怎么记住前一个线程的数据状态的?有这样一个结构 TContext, 它基本上是一个 CPU 寄存器的集合, 线程是数据就是通过这个结构切换的, 我们也可以通过 GetThreadContext 函数读取寄存器看看. 附上这个结构 TContext(或叫: CONTEXT、_CONTEXT) 的定义:--------------------------------------------------------------------------------PContext = ^TContext;_CONTEXT = record  ContextFlags: DWORD;  Dr0: DWORD;  Dr1: DWORD;  Dr2: DWORD;  Dr3: DWORD;  Dr6: DWORD;  Dr7: DWORD;  FloatSave: TFloatingSaveArea;  SegGs: DWORD;  SegFs: DWORD;  SegEs: DWORD;  SegDs: DWORD;  Edi: DWORD;  Esi: DWORD;  Ebx: DWORD;  Edx: DWORD;  Ecx: DWORD;  Eax: DWORD;  Ebp: DWORD;  Eip: DWORD;  SegCs: DWORD;  EFlags: DWORD;  Esp: DWORD;  SegSs: DWORD;end;-------------------------------------------------------------------------------- CreateThread 的最后一个参数是 "线程的 ID";既然可以返回句柄, 为什么还要输出这个 ID? 现在我知道的是:1、线程的 ID 是唯一的; 而句柄可能不只一个, 譬如可以用 GetCurrentThread 获取一个伪句柄、可以用 DuplicateHandle 复制一个句柄等等.2、ID 比句柄更轻便. 在主线程中 GetCurrentThreadId、MainThreadID、MainInstance 获取的都是主线程的 ID.-------------------------------------------------------------------------------- 啰哩啰嗦一大些, 才说了 CreateThread 一个参数, 下篇继续. 线程的学习还在入门中, 把我的理解写在这, 最期望的收获是得到指正.

(0)

相关推荐

  • Linux下的多线程编程和fork()函数详解

     一.fork()函数 在操作系统的基本概念中进程是程序的一次执行,且是拥有资源的最小单位和调度单位(在引入线程的操作系统中,线程是最小的调度单位).在Linux系统中 创建进程有两种方式:一是由操作 ...

  • MFC多线程编程实例

    一般情况下,调用AfxBeginThread()来一次性地创建并启动一个线程,但是也可以通过两步法来创建线程:首先创建CWinThread类的一个 对象,然后调用该对象的成员函数CreateThrea ...

  • MFC对多线程编程的支持

    摘要:关于MFC对多线程编程的支持深入研究. 步骤/方法 01 例程3 MultiThread3 传送一个结构体给一个线程函数也是可能的,可以通过传送一个指向结构体的指针参数来完成.先定义一个结构体: ...

  • Linux下如何实现shell多线程编程以提高应用程序的响应

    Linux中多线程编程拥有提高应用程序的响应、使多cpu系统更加有效等优点,下面小编将通过Linux下shell多线程编程的例子给大家讲解下多线程编程的过程,一起来了解下吧。 #!/bin/bash ...

  • 在Linux系统上进行openmp多线程编程的方法

    OpenMP是一种多处理器多线程的编程语言,能够支持多个平台,包括Linux系统,那么Linux下要如何进行openmp多线程编程呢?一起来了解下吧。 关键语法: 代码如下: #inlcude 《om ...

  • linux多线程编程详解教程

    这篇文章主要介绍了linux多线程编程详解教程,提供线程通过信号量实现通信的代码,大家参考使用吧 线程分类 线程按照其调度者可以分为用户级线程和核心级线程两种。 (1)用户级线程 用户级线程主要解决的 ...

  • VBA编程中的Resize函数怎样使用?

    VBA编程中的Resize函数怎样使用? 操作方法 01 打开本地的excle软件,选中两个单元格. 02 然后在顶部菜单栏中找到"开发工具"->"Visual B ...

  • java实现多线程编程

    操作方法 01 本文详细讲述一下Java实现多线程编程的三种方法,多线程领域里实现多线程编程的总体思路就是重构run()方法以实现自己所需的功能,然后创建线程对象调用start()方法来启动线程,然后 ...

  • linux系统下openmp多线程编程示例

    关键语法: 复制代码 代码如下: #inlcude <omp.h> #pragma omp parallel for #pragma omp for reduction(+: 变量) #p ...