Win32线程——在某个线程内终止另一个正在运行的线程(2)(Event对象)

《Win32多线程程序设计》

Win32 中最具弹性的同步机制就属 events 对象了。 Event 对象是一种核心对象,它的唯一目的就是成为激发状态或未激发状态。这两种状态全由程序来控制,不会成为Wait…() 函数的副作用。
Event 对象之所以有大用途,正是因为它们的状态完全在你掌控之下。Mutexes 和 sem aphores 就不一样了,它们的状态会因为诸如WaitForSingleObject() 之类的函数调用而变化。所以, 你可以精确告诉一个event 对象做什么事,以及什么时候去做。

Win32在主线程中安全的终止一个子线程

#include 
#include 
#include 
#include 

DWORD WINAPI Thread(void *arg) {
    HANDLE hEvent = (HANDLE)arg;
    ResetEvent(hEvent); // 设置hEvent为非激发状态
    while (1) {
        DWORD waitRet = WaitForSingleObject(hEvent, 1000); // 等待hEvent变为激发状态,超时1s
        if (WAIT_OBJECT_0 == waitRet) {
            printf("%#p被激发,退出此线程\n", hEvent); 
            break;
        }
        printf("Thread(%#p), time=%d\n", hEvent, (int)time(NULL));
    }
    return 0;
}

int main(void) {
    HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // 创建一个手动控制、初始为非激发状态、未命名的Event对象
    HANDLE hThread = CreateThread(NULL, 0, Thread, hEvent, 0, NULL);

    Sleep(5000); // 5s后结束Thread线程
    SetEvent(hEvent); // 设置hEvent为激发状态
    DWORD waitRet = WaitForSingleObject(hThread, INFINITE);
    switch (waitRet) {
            case WAIT_TIMEOUT: printf("%#p处于非激发状态, 超时\n", hThread); break;
            case WAIT_ABANDONED: printf("%#p是一个未释放的Mutex对象\n", hThread); break;
            case WAIT_OBJECT_0: printf("%#p处于激发状态\n", hThread); break;
            default: printf("WaitForSingleObject(%#p)=%lu,{%ld}\n", hThread, WAIT_FAILED, GetLastError()); break;
    }

    CloseHandle(hThread);
    CloseHandle(hEvent);

    return 0;
}

Win32线程——在某个线程内终止另一个正在运行的线程(2)(Event对象)_第1张图片

Win32在主线程中安全的终止多个子线程

WaitForMultipleObjects 最多可等待64(MAXIMUM_WAIT_OBJECTS)个核心对象。

#include 
#include 
#include 
#include 

#define THREAD_NUM 2

DWORD WINAPI Thread(void *arg) {
    HANDLE hEvent = (HANDLE)arg;
    ResetEvent(hEvent); // 设置hEvent为非激发状态
    while (1) {
        DWORD waitRet = WaitForSingleObject(hEvent, 1000); // 等待hEvent变为激发状态,超时1s
        if (WAIT_TIMEOUT != waitRet) {
            printf("WaitForSingleObject(%#p)=%lu,退出此线程\n", hEvent, waitRet); 
            break;
        }
        printf("Thread(%#p), time=%d\n", hEvent, (int)time(NULL));
    }
    return 0;
}

int main(void) {
    HANDLE hThreadArray[THREAD_NUM], hEventArray[THREAD_NUM];
    for (int i = 0; i < THREAD_NUM; i++) {
        hEventArray[i] = CreateEvent(NULL, TRUE, FALSE, NULL); // 创建一个手动控制、初始为非激发状态、未命名的Event对象
        hThreadArray[i] = CreateThread(NULL, 0, Thread, hEventArray[i], 0, NULL);
    }

    for (int i = 0; i < THREAD_NUM; i++) {
        Sleep(3000); // 每隔3s终止一个线程
        SetEvent(hEventArray[i]); // 设置一个Event对象为激发状态
    }
    DWORD waitRet = WaitForMultipleObjects(THREAD_NUM, hThreadArray, TRUE, INFINITE); // 等待所有线程,无限超时
    switch (waitRet) {
            case WAIT_TIMEOUT: printf("存在对象处于非激发状态, 超时\n"); break;
            case WAIT_ABANDONED_0: printf("所有对象处于激发状态,但其中有未释放的Mutex对象\n"); break;
            case WAIT_OBJECT_0: printf("所有对象处于激发状态\n"); break;
            default: printf("WaitForMultipleObjects()=%lu,{%ld}\n", WAIT_FAILED, GetLastError()); break;
    }

    for (int i = 0; i < THREAD_NUM; i++) {
        CloseHandle(hThreadArray[i]);
        CloseHandle(hEventArray[i]);
    }

    return 0;
}

Win32线程——在某个线程内终止另一个正在运行的线程(2)(Event对象)_第2张图片

MFC安全的关闭窗口

BOOL xxx::OnInitDialog()
{
    CDialog::OnInitDialog();

    m_picDirHandle = (HANDLE)_beginthread(&CheckPicDirFunc, 1024 * 1024 * 10, this);
    m_photoSocketHandle = (HANDLE)_beginthread(&PhotoSocketFunc, 1024 * 1024 * 10, this);   
    m_dirEvtHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
    m_sockEvtHandle = CreateEvent(NULL, TRUE, FALSE, NULL);

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void xxx::OnClose()
{
    SetEvent(m_dirEvtHandle);
    SetEvent(m_sockEvtHandle);

    HANDLE funcHandle[2] = {m_picDirHandle, m_photoSocketHandle};
    DWORD dwRet = WaitForMultipleObjects(ARRAY_LENGTH(funcHandle), funcHandle, FALSE, INFINITE);
    switch (dwRet) {  
        case WAIT_OBJECT_0:
            LOG("WaitForMultipleObjects()---CheckPicDirFunc线程安全退出");
        case WAIT_OBJECT_0 + 1:
            LOG("WaitForMultipleObjects()---PhotoSocketFunc线程安全退出");
            break;
        default:
            LOG("WaitForMultipleObjects()---释放资源失败");
            break;
    }

    CloseHandle(m_dirEvtHandle);
    CloseHandle(m_sockEvtHandle);

    CDialog::OnClose();
}

void xxx::PhotoSocketFunc(void *p_para) {
    xxx *dlg = (xxx *)p_para;

    ResetEvent(dlg->m_sockEvtHandle);
    while (TRUE) {
        if (WAIT_OBJECT_0 == WaitForSingleObject(dlg->m_sockEvtHandle, 0)) {
            LOG("PhotoSocketFunc() Exit\n");
            break;
        }
        printf("thread test photo\n");
        Sleep(10);
    }
}

void xxx::CheckPicDirFunc(void *p_para) {
    xxx *dlg = (xxx *)p_para;   

    ResetEvent(dlg->m_dirEvtHandle);
    while (TRUE) {
        if (WAIT_OBJECT_0 == WaitForSingleObject(dlg->m_dirEvtHandle, 1000 * 60 * 60 * 2)) { // 超时2小时 
            LOG("CheckPicDirFunc() Exit\n");
            break;
        }
        printf("thread test dir\n");
        Sleep(10);
    }
}

你可能感兴趣的:(▷--○,WinThread)