PoEdu培训 Windows班 第三十五课 Windows 内核对象(二) 信号状态
文章类别: 培训笔记 0 评论

PoEdu培训 Windows班 第三十五课 Windows 内核对象(二) 信号状态

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

Windows 内核对象(二) 信号状态

Signal状态

内核对象主要是用于跨进程的同步

Wait的三种结果

让我们用一段代码来观察

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

UINT WINAPI ThreadFunc(LPVOID lParam)
{
    // 休眠5秒, 会获得 等待超时
    // 注释掉此代码, 会获得 等待成功
    Sleep(5000);
    return 0;
}

INT _tmain()
{
    _tsetlocale(0, TEXT(""));
    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, NULL, 0, NULL);

    DWORD dwWaitRet = -1;
    //dwWaitRet = WaitForSingleObject(hThread, INFINITE);    // 等待30天
    dwWaitRet = WaitForSingleObject(hThread, 1000);    // 等等1秒

    switch (dwWaitRet)
    {
    // hThread 为INVALID_HANDLE_VALUE, 等待超时
    case WAIT_TIMEOUT:
        _tprintf(TEXT("等待超时!\n"));
        break;
    case WAIT_OBJECT_0:
        _tprintf(TEXT("等待成功!\n"));
        break;
    // hThread 为NULL, 等待失败
    case WAIT_FAILED:
        _tprintf(TEXT("等待失败!\n"));
        break;
    default:
        break;
    }

    CloseHandle(hThread);
    return 0;
}

注意:
当等待的HANDLE为NULL时, 会等待失败
当等待的HANDLE为INVALID_HANDLE_VALUE时, 会等待超时
如果等待时间为INFINITE, HANDLE为INVALID_HANDLE_VALUE, 线程将永久等待

Wait的注意事项

首先, 我们拿一个小例子测试WaitForMutipleObjects

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

UINT WINAPI ThreadFunc(LPVOID lParam)
{
    // 休眠
    Sleep((INT)lParam);
    return 0;
}

/////// WaitForMultipleObjects
INT _tmain()
{
    _tsetlocale(0, TEXT(""));
    HANDLE hThreads[2] = { INVALID_HANDLE_VALUE };
    hThreads[0] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (LPVOID)1000, 0, NULL);
    hThreads[1] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (LPVOID)3000, 0, NULL);

    DWORD dwWaitRet = -1;
    //dwWaitRet = WaitForMultipleObjects(2, hThreads, FALSE, 200);    // 等200毫秒
                                                                    // 等待200毫秒, 等待超时
    //dwWaitRet = WaitForMultipleObjects(2, hThreads, FALSE, 2000);    // 等2秒
                                                                    // 等待2秒, 等待成功
    dwWaitRet = WaitForMultipleObjects(2, hThreads, FALSE, INFINITE);    // 等永久
                                                                    // 等待永久, 等待成功

    switch (dwWaitRet)
    {
    case WAIT_TIMEOUT:
        _tprintf(TEXT("等待超时!\n"));
        break;
        // WaitForMultipleObjects等待所有为TRUE时, WAIT_OBJECT_0永远不会进入
    case WAIT_OBJECT_0:
        _tprintf(TEXT("等待成功!\n"));
        break;
    case WAIT_FAILED:
        _tprintf(TEXT("等待失败!\n"));
        break;
    default:
        break;
    }

    CloseHandle(hThreads[0]);
    CloseHandle(hThreads[1]);
    return 0;
}

当我们不等待所以线程完成的时候

那如果要必须等到线程2执行结束应该怎么办?
我们写出如下代码:

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

UINT WINAPI ThreadFunc(LPVOID lParam)
{
    // 休眠
    Sleep((INT)lParam);
    return 0;
}

/////// WaitForMultipleObjects
INT _tmain()
{
    _tsetlocale(0, TEXT(""));
    HANDLE hThreads[2] = { INVALID_HANDLE_VALUE };
    hThreads[0] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (LPVOID)1000, 0, NULL);
    hThreads[1] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (LPVOID)3000, 0, NULL);

    DWORD dwWaitRet = -1;

    // 等待指定线程结束
    BOOL bLoop = TRUE;
    while (bLoop)
    {
        dwWaitRet = WaitForMultipleObjects(2, hThreads, FALSE, 100);    // 等100毫秒
        switch (dwWaitRet)
        {
        case WAIT_TIMEOUT:
            _tprintf(TEXT("等待超时! 进行下一次等待....\n"));
            break;
        case WAIT_OBJECT_0:
            _tprintf(TEXT("线程 1 执行成功!\n"));
            break;
        case WAIT_OBJECT_0 + 1:
            _tprintf(TEXT("线程 2 执行成功!\n"));
            bLoop = FALSE;
            break;
        case WAIT_FAILED:
            _tprintf(TEXT("等待失败!\n"));
            break;
        default:
            break;
        }
    }

    CloseHandle(hThreads[0]);
    CloseHandle(hThreads[1]);
    return 0;
}

那这是为什么呢?

我们改写代码:

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

UINT WINAPI ThreadFunc(LPVOID lParam)
{
    // 休眠
    Sleep((INT)lParam);
    return 0;
}

/////// WaitForMultipleObjects
INT _tmain()
{
    _tsetlocale(0, TEXT(""));
    HANDLE hThreads[2] = { INVALID_HANDLE_VALUE };
    hThreads[0] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (LPVOID)1000, 0, NULL);
    hThreads[1] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (LPVOID)3000, 0, NULL);

    DWORD dwWaitRet = -1;

    // 等待指定线程结束
    BOOL bLoop = TRUE;
    while (bLoop)
    {
        dwWaitRet = WaitForMultipleObjects(2, hThreads, FALSE, 100);    // 等100毫秒

        DWORD dwRet = WaitForSingleObject(hThreads[1], 10);    // 等10毫秒
        if (dwRet == WAIT_OBJECT_0 + 1)
            _tprintf(TEXT("===> 线程 2 已经执行成功了!\n"));

        switch (dwWaitRet)
        {
        case WAIT_TIMEOUT:
            _tprintf(TEXT("等待超时! 进行下一次等待....\n"));
            break;
        case WAIT_OBJECT_0:
            _tprintf(TEXT("线程 1 执行成功!\n"));
            break;
        case WAIT_OBJECT_0 + 1:
            _tprintf(TEXT("线程 2 执行成功!\n"));
            bLoop = FALSE;
            break;
        case WAIT_FAILED:
            _tprintf(TEXT("等待失败!\n"));
            break;
        default:
            break;
        }
    }

    CloseHandle(hThreads[0]);
    CloseHandle(hThreads[1]);
    return 0;
}

所以, 一定要注意WaitForMultipleObjects等待多个内核对象但是并不等待所有内核对象完成的情况

未完待续...

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

回复