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\n", pmd->val1);
    printf("%d\n", 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。除非刪除已經收到通知的句柄,否則代碼就無法正確地運行

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM