zoukankan      html  css  js  c++  java
  • 【VS开发】CreateThread给线程函数传递的参数

    CreateThread给线程函数传递的参数

     
    复制代码
    HANDLE WINAPI CreateThread
    ( 
      __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes, // 指向SECURITY_ATTRIBUTES 的指针,为新线程指定安全描述 
      __in       SIZE_T dwStackSize, // 初始化线程堆栈尺寸 
      __in       LPTHREAD_START_ROUTINE lpStartAddress, //线程函数所指向的地址起始函数   
    __in_opt   LPVOID lpParameter, // 给线程函数传递的参数   
    __in       DWORD dwCreationFlags, // 有关线程的标志  
     __out_opt  LPDWORD lpThreadId //系统分配给线程的ID
    
     );  
    复制代码

     

    ----第一个参数是安全属性,一般设为null,使用缺省的安全属性。当我们想此线程有另外的子进程时,可改变它的属性。 
    ----第二个参数是线程堆栈尺寸,一般设为0,表示与此应用的堆栈尺寸相同,即主线程与创建的线程一样长度的堆栈。并且其长度会根据需要自动变长。 
    ----第三个参数,也是最重要的一个,是一个指向函数名的指针,或者函数名字 
    ----第四个参数是你需要向线程函数传递的参数,一般是一个指向结构的指针。不需传递参数时,则这个参数设为null。 
    ----第五个参数,传入与线程有关的一些标志,如果是CREATE_SUSPENDED,则创建一个挂起的线程,即这个线程本身已创建,它的堆栈也已创建。但这个线程不会被分配给CPU时间,只有当ResumeThread函数被调用后才能执行;当然,也可以调用SuspendThread函数再次挂起线程。要是标志为0,那么一旦建立线程,线程函数就被立即调用。一般传为0即可。 ----第六个参数是系统分配给这个线程的唯一的ID标志 

     

    复制代码
    // MultiTread2.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    #include <windows.h>
    #include <stdio.h>
    
    #define MAX_THREADS 10
    
    typedef struct MyData
    {
        int val1;
        int val2;
        //char key[32];
    }MYDATA;
    
    DWORD WINAPI ThreadProc(LPVOID lpParam)
    {
        MYDATA *pmd = (MYDATA *)lpParam;
        printf("%d
    ", pmd->val1);
        printf("%d
    ", pmd->val2);
        return 0;
    }
    
    DWORD(WINAPI *pThreadProc)(LPVOID lpParam);
    
    void fun()
    {
        pThreadProc = ThreadProc;
        MYDATA mydt[MAX_THREADS];
    
        HANDLE hThread[MAX_THREADS];
        int i;
        for (i = 0; i < MAX_THREADS; i++)
        {
            mydt[i].val1 = i;
            mydt[i].val2 = i + 1;
            hThread[i] = CreateThread(
                NULL,// default security attributes
                0,// use default stack size
                pThreadProc,// thread function
                &mydt[i],// argument to thread function
                0, // use default creation flags
                NULL);
            if (hThread[i] == NULL)
            {
                ExitProcess(i);
            }
        }
        // Wait until all threads have terminated.
        WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); //这样传给回调函数的参数不用定位static或者new出来的了
        // Close all thread handles upon completion. 
        for (i = 0; i < MAX_THREADS; i++)
        {
            CloseHandle(hThread[i]);
        }
    
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        fun();
        getchar();
        return 0;
    }
    复制代码

     

    注意:传给函数的参数,要保证当运行回调函数时候,参数不能被销毁。

    比如这里参数是局部变量栈。

    如果将 

     WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); //这样传给回调函数的参数不用定位static或者new出来的了
    屏蔽,
    那么传递给回调函数的参数就可能已经被销毁,调用函数的时候就会出错、


    除非将传入的参数定义为static 或者其他在调用完所有线程前不被销毁的变量

    WaitForMultipleObjects
    WaitForSingleObject的返回值能够指明调用线程为什么再次变为可调度状态。如果线程等待的对象变为已通知状态,那么返回值是 WAIT_OBJECT_0。如果设置的超时已经到期,则返回值是WAIT_TIMEOUT。如果将一个错误的值(如一个无效句柄)传递给 WaitForSingleObject,那么返回值将是WAIT_FAILED(若要了解详细信息,可调用GetLastError)。
    下面这个函数WaitForMultipleObjects与WaitForSingleObject函数很相似,区别在于它允许调用线程同时查看若干个内核对象的已通知状态:
    DWORD WaitForMultipleObjects(
        DWORD dwCount,
       CONST HANDLE* phObjects,
       BOOL fWaitAll,
       DWORD dwMilliseconds
    );

     

    dwCount参数用于指明想要让函数查看的内核对象的数量。这个值必须在1与MAXIMUM_WAIT_OBJECTS(在Windows头文件中定义为64)之间。
     
    phObjects参数是指向内核对象句柄的数组的指针。
    可以以两种不同的方式来使用WaitForMultipleObjects函数。
    一种方式是让线程进入等待状态,直到指定内核对象中的任何一个变为已通知状态。
    另一种方式是让线程进入等待状态,直到所有指定的内核对象都变为已通知状态。
    fWaitAll参数告诉该函数,你想要让它使用何种方式。
    如果为该参数传递TRUE,那么在所有对象变为已通知状态之前,该函数将不允许调用线程运行。
    dwMilliseconds参数的作用与它在WaitForSingleObject中的作用完全相同。如果在等待的时候规定的时间到了,那么该函数无论如何都会返回。
    同样,通常为该参数传递INFINITE,但是在编写代码时应该小心,以避免出现死锁情况。
     
    WaitForMultipleObjects函数的返回值告诉调用线程,为 什么它会被重新调度。可能的返回值是WAIT_FAILED和WAIT_TIMEOUT,这两个值的作用是很清楚的。
    如果fWaitAll参数传递 TRUE,同时所有对象均变为已通知状态,那么返回值是WAIT_OBJECT_0。
    如果为fWaitAll传递FALSE,那么一旦任何一个对象变为已 通知状态,该函数便返回。
    在这种情况下,你可能想要知道哪个对象变为已通知状态。返回值是WAIT_OBJECT_0 与(WAIT_OBJECT_0 + dwCount-1)之间的一个值。
    换句话说,如果返回值不是WAIT_TIMEOUT,也不是WAIT_FAILED,那么应该从返回值中减去 WAIT_OBJECT_0。产生的数字是作为第二个参数传递给WaitForMultipleObjects的句柄数组中的索引。
    该索引说明哪个对象变 为已通知状态。
    
    
    复制代码
    说明这一情况的一些示例代码:
    HANDLE h[3];
    h[0] = hProcess1;
    h[1] = hProcess2;
    h[2] = hProcess3;
    DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000);
    switch(dw)
    {
       case WAIT_FAILED:
          // Bad call to function (invalid handle?)
          break;
       case WAIT_TIMEOUT:
          // None of the objects became signaled within 5000 milliseconds.
          break;
       case WAIT_OBJECT_0 + 0:
          // The process identified by h[0] (hProcess1) terminated.
          break;
       case WAIT_OBJECT_0 + 1:
          // The process identified by h[1] (hProcess2) terminated.
          break;
       case WAIT_OBJECT_0 + 2:
          // The process identified by h[2] (hProcess3) terminated.
          break;
    }
    复制代码
    
    

    如果为fWaitAll参数传递 FALSE,WaitForMultipleObjects就从索引0开始向上对句柄数组进行扫描,同时已通知的第一个对象终止等待状态。

    这可能产生一些 你不希望有的结果。

    例如,通过将3个进程句柄传递给该函数,你的线程就会等待3个子进程终止运行。如果数组中索引为0的进程终止运 行,WaitForMultipleObjects就会返回。这时该线程就可以做它需要的任何事情,然后循环反复,等待另一个进程终止运行。

    如果该线程传 递相同的3个句柄,该函数立即再次返回WAIT_OBJECT_0。除非删除已经收到通知的句柄,否则代码就无法正确地运行

  • 相关阅读:
    算法训练 P1103
    算法训练 表达式计算
    算法训练 表达式计算
    基础练习 时间转换
    基础练习 字符串对比
    Codeforces 527D Clique Problem
    Codeforces 527C Glass Carving
    Codeforces 527B Error Correct System
    Codeforces 527A Glass Carving
    Topcoder SRM 655 DIV1 250 CountryGroupHard
  • 原文地址:https://www.cnblogs.com/huty/p/8517765.html
Copyright © 2011-2022 走看看