Windows多线程编程(1)创建线程

    CreateThread函数为进程创建一个线程。必须给创建的线程声明一个开始地址,使这个线程可以从这个地址开始执行。一般的,这个地址就是程序里定义的一个函数的名字。这个函数有一个参数,一个DWORD类型的返回值。进程可以拥有运行同一函数的多个线程。

    下面的例子说明怎么样创建一个新线程,这个线程执行一个本地定义的函数:ThreadProc。被建立的线程利用一块动态开辟的缓存,给每一个线程对应的函数传递唯一的信息(说白了,就是利用指针向线程函数传递参数)。线程函数负责释放内存。
    主线程利用WaitForMultipleObjects函数来等待所有工作线程运行终止。需要注意的是,在工作线程终止之前关闭了它的句柄(HANDLE)不会终止工作线程的运行。但是,句柄会在之后的调用中不可用。
(程序注释是我加的)
#include <windows.h>
#include <strsafe.h>

#define MAX_THREADS 3
#define BUF_SIZE 255

typedef struct _MyData {               //这个就是线程参数,可以自定义
    int val1;
    int val2;
} MYDATA, *PMYDATA;

DWORD WINAPI ThreadProc( LPVOID lpParam )   //线程函数必须定义成这个样子,
                                            //形式参数是一个LPVOID指针

    HANDLE hStdout;
    PMYDATA pData;

    TCHAR msgBuf[BUF_SIZE];
    size_t cchStringSize;
    DWORD dwChars;

    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    if( hStdout == INVALID_HANDLE_VALUE )
        return 1;

    // Cast the parameter to the correct data type.

    pData = (PMYDATA)lpParam;                         //这里就是把参数强制转换成
                                                      //自定义的类型

    // Print the parameter values using thread-safe functions.

    StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d "), 
        pData->val1, pData->val2); 
    StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
    WriteConsole(hStdout, msgBuf, cchStringSize, &dwChars, NULL);

    // Free the memory allocated by the caller for the thread 
    // data structure.

    HeapFree(GetProcessHeap(), 0, pData);

    return 0; 

 
void main()
{
    PMYDATA pData;
    DWORD dwThreadId[MAX_THREADS];
    HANDLE hThread[MAX_THREADS]; 
    int i;

    // Create MAX_THREADS worker threads.

    for( i=0; i<MAX_THREADS; i++ )
    {
        // Allocate memory for thread data.

        pData = (PMYDATA) HeapAlloc(GetProcessHeap(), 
                                    HEAP_ZERO_MEMORY,
                                    sizeof(MYDATA));

        if( pData == NULL )
            ExitProcess(2);

        // Generate unique data for each thread.

        pData->val1 = i;
        pData->val2 = i+100;

        hThread[i] = CreateThread(                //创建线程的winapi函数
            NULL,              // default security attributes
            0,                 // use default stack size  
            ThreadProc,        // thread function 
            pData,             // argument to thread function 
            0,                 // use default creation flags 
            &dwThreadId[i]);   // returns the thread identifier 
 
        // Check the return value for success. 
 
        if (hThread[i] == NULL) 
        {
            ExitProcess(i);
        }
    }

    // Wait until all threads have terminated.

    WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE);

    // Close all thread handles upon completion.

    for(i=0; i<MAX_THREADS; i++)
    {
        CloseHandle(hThread[i]);
    }
}
    ThreadProc函数没有使用C运行时库(CRT),因为如果不使用多线程CRT(multithreaded CRT),它的很多函数都不是线程安全的。如果想在ThreadProc中使用CRT,用_beginthreadex创建线程。
    如果创建线程在新线程之前退出,那么传递一个本地变量的地址是危险的,因为指针将会无效。所以,传递一个动态开辟的内存,或者创建线程等待新线程终止都可以避免这个情况发生。也可以利用全局变量将参数从创建线程传递到新线程。如果利用全局变量,就很有必要做好互斥工作。查看《多线程同步》可以得到更多信息。
    创建线程可以利用CreateThread重的几个参数声明新线程的几个特征:
    1、新线程句柄的安全属性。这些安全属性包含一个继承标志,它们可以决定这个句柄能否被子进程继承。安全属性也包含一个安全描述符,有了这个描述符,在之后对线程句柄的所有操作之前,系统都要检查权限。(我:一般情况下直接传递NULL)
    2、新线程的初始栈尺寸。线程的栈是在进程的内存空间中自动生成的;系统在需要的时候扩大栈的尺寸,在线程终止的时候回收栈。(我:一般情况下直接默认)
    3、创建标志允许创建一个挂起的线程。创建这样的线程之后,调用ResumeThread函数环形线程。

发布了21 篇原创文章 · 获赞 6 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/Perfecter/article/details/41687041
今日推荐