PoEdu培训 Windows班 第二十课 Windows线程
文章类别: 培训笔记 0 评论

PoEdu培训 Windows班 第二十课 Windows线程

文章类别: 培训笔记 0 评论

Windows 线程

线程函数

我们的main/WinMain函数其实就是我们的线程入口函数.

线程堆栈

使用CreateThreadAPI可以创建一个线程.

CreateThread API

HANDLE WINAPI CreateThread(
  _In_opt_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,    // 线程安全结构体, 一般设置为NULL
  _In_      SIZE_T                 dwStackSize,            // 堆栈大小, 可为0, 由编译器决定, 单位是BYTE
  _In_      LPTHREAD_START_ROUTINE lpStartAddress,        // 线程开始地址(入口函数)
  _In_opt_  LPVOID                 lpParameter,            // 线程的参数
  _In_      DWORD                  dwCreationFlags,        // 运行方式
  _Out_opt_ LPDWORD                lpThreadId            // 线程的标识符, 输出参数, 可为NULL
);

堆栈大小的设置

线程入口函数

线程参数

#include <Windows.h>

DWORD WINAPI ThreadMain(LPVOID lParam)
{
    int nParam = (INT)lParam;
      return 0;    // 线程退出代码
}

int main()
{
    HANDLE hThread = CreateThread(NULL, 0, ThreadMain, (LPVOID)0xFFFF, 0, NULL);
    CloseHandle(hThread);
    return 0;
}

线程运行方式

线程标识

主线程退出和其他线程退出的区别

// 例子1
// 主线程启动子线程, 主线程消亡, 子线程也消亡

#include <Windows.h>
#include <tchar.h>

DWORD WINAPI ThreadMain(LPVOID lParam)
{
    int nParam = (INT)lParam;
    Sleep(100);
    _tprintf(TEXT("nParam:[%d]\n"), nParam);
      return 0;    // 线程退出代码
}

int main()
{
    HANDLE hThread = CreateThread(NULL, 0, ThreadMain, (LPVOID)0xFFFF, 0, NULL);
    CloseHandle(hThread);
    // Sleep(200);    // 取消或注释这一句查看运行效果
    return 0;
}
// 例子2
// 线程抢占执行
// 子线程A启动子线程B的消亡问题

#include <Windows.h>
#include <tchar.h>

DWORD WINAPI ThreadSubMain(LPVOID lParam)
{
    int nParam = (INT)lParam;
    _tprintf(TEXT("nParam:[%d]\n"), nParam);
      return 0;    // 线程退出代码
}

DWORD WINAPI ThreadMain(LPVOID lParam)
{
    int nParam = (INT)lParam;

    HANDLE hThread = CreateThread(NULL, 0, ThreadSubMain, (LPVOID)0x64, 0, NULL);
    CloseHandle(hThread);

    Sleep(1);    // 关键在这一句 
    // 这一句被注释掉, 会先输出-1, 后输出100, 不注释, 就会先输出100, 后输出-1
    // 这是因为, Sleep会导致线程休眠, 让出CPU的时间片, 由第二个线程进行抢占执行

    _tprintf(TEXT("nParam:[%d]\n"), nParam);
      return 0;    // 线程退出代码
}

int main()
{
    HANDLE hThread = CreateThread(NULL, 0, ThreadMain, (LPVOID)0xFFFFFFFF, 0, NULL);
    CloseHandle(hThread);

    while (TRUE)
    {
        Sleep(100);
    }

    return 0;
}

线程间参数传递

在上面的例子中, 我们简单的使用了一下线程的参数, 只传递了数字.

#include <Windows.h>
#include <tchar.h>

class CThreadParam
{
public:
    INT m_nNum;
};

DWORD WINAPI ThreadOtherMain(LPVOID lParam)
{
    Sleep(100);    // 模拟让ThreadMain运行完成
    CThreadParam* demo = (CThreadParam*)lParam;
    _tprintf(TEXT("m_nNum:[%d]\n"), demo->m_nNum);
    return 0;
}

DWORD WINAPI ThreadMain(LPVOID lParam)
{
    _tprintf(TEXT("In ThreadMain....\n"));
    Sleep(100);

    CThreadParam demo;
    demo.m_nNum = 100;

    // 这时候的传值是不正确的, 因为没有保证 demo 的有效性
    CloseHandle(CreateThread(NULL, 0, ThreadOtherMain, &demo, 0, NULL));
    _tprintf(TEXT("Finish ThreadMain....\n"));
    return 0;
}

INT main()
{
    CThreadParam param;
    // 这里这样传参是没问题的, 因为我们进行了等待, 一定可以保证 param 的有效性
    HANDLE hThread = CreateThread(NULL, 0, ThreadMain, &param, 0, NULL);

    _tprintf(TEXT("Will Exec WaitForSingleObject....\n"));
    // 有可能先出现Will... , 也可能先出现 In ThreadMain. 不一定先执行谁
    // 可以利用 Sleep(1) 切换线程状态, 控制线程执行顺序

    WaitForSingleObject(hThread, INFINITE);        // 等待线程完成
    CloseHandle(hThread);    // 关闭线程句柄
    return 0;
}

未完待续...

如有错误,请提出指正!谢谢.

回复