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。除非删除已经收到通知的句柄,否则代码就无法正确地运行

  • 相关阅读:
    二叉树 Java 实现 前序遍历 中序遍历 后序遍历 层级遍历 获取叶节点 宽度 ,高度,队列实现二叉树遍历 求二叉树的最大距离
    Java:JUnit4使用详解
    Java 常用数据结构对象的实现原理 集合类 List Set Map 哪些线程安全 (美团面试题目)
    JAVA里的布尔运算符-甲骨文面试题
    try catch finally 用法
    Java的JDBC事务详解
    Java开发中JDBC连接数据库代码和步骤
    WebUploader文件图片上传插件的使用
    webuploader解决不能重复上传问题及一些常见问题处理
    HTML5 input file控件使用accept过滤限制的文件类型以及在谷歌下打开很慢的问题
  • 原文地址:https://www.cnblogs.com/huty/p/8517764.html
Copyright © 2011-2022 走看看