zoukankan      html  css  js  c++  java
  • windows多线程编程

    当进程结束后所有线程都终止。多线程编程最大的问题在于共享数据的访问控制。
    直接用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得到错误代码

  • 相关阅读:
    第11组 团队Git现场编程实战
    团队项目-需求分析报告
    团队项目-选题报告
    第10组 Alpha事后诸葛亮
    第10组 Alpha冲刺(6/6)
    第10组 Alpha冲刺(5/6)
    第10组 Alpha冲刺(4/6)
    第10组 Alpha冲刺(3/6)
    第10组 Alpha冲刺(2/6)
    第10组 Alpha冲刺(1/6)
  • 原文地址:https://www.cnblogs.com/shockerjue/p/2837654.html
Copyright © 2011-2022 走看看