《Win32多线程程序设计》(10)---如何终止一个线程

13 篇文章 0 订阅
6 篇文章 0 订阅

结束一个线程,听起来好容易,但是结束程序必须按次序进行,以避免发生race  conditions。让程序依次序进行是非常重要的,特别是在程序要结束之前。结束一个程序就好像拆除一栋建筑物一样,在你以推土机轧平它之前,你必须确定每一个人都安全离开了屋子。结束一个程序也是这样,每一个线程都被迫结束,不管它进行到哪里。

利用 TerminateThread() 放弃一个线程

BOOL TerminateThread(
HANDLE hThread,
DWORD dwExitCode
);
参数
hThread  欲令其结束之线程的handle。该线程就是我们的行动目标。
dwExitCode  该线程的结束代码。
返回值
如果函数成功,则传回TRUE。如果失败,则传回FALSE。GetLastError() 可以获知更多细节。


TerminateThread() 强迫其行动目标(一个线程)结束,手段激烈而有力,甚至不允许该线程有任何“挣扎”的机会。这带来的副作用便是,线程没有机会在结束前清理自己。对线程而言,这可能导致前功尽弃。这个函数不会在目标线程中丢出一个异常情况(exception),目标线程在核心层面就被根本抹杀了。目标线程没有机会捕捉所谓的“结束请求”,并从而获得清理自己的机会。
还有另一个令人不愉快的情况。目标线程的堆栈没有被释放掉,于是可能会引起一大块内存泄漏(memory leak)。而且,任何一个与此线程有附着关系的DLLs 也都没有机会获得“线程解除附着”的通知。
此函数唯一可以预期并依恃的是,线程handle 将变成激发状态(译注:因为线程结束了),并且传回dw ExitCode 所指定的结束代码。
这个函数所带来的隐伏危机还包括:如果线程正进入一个critical section 之中,该critical  section 将因此永远处于锁定状态,因为critical  section 不像mutex 那样有所谓的" abandoned" 状态。如果目标线程正在更新一份数据结构,这份数据结构也将永远处于不稳定状态。没有任何方法可以阻止这些问题的发生。
我的结论是:离Term inateThread() 远远地!

设立一个标记

Win32 核准的做法是在你的程序代码中设立一个标记,利用其值来要求线程结束自己。

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#include "MtVerify.h"

DWORD WINAPI ThreadFunc(LPVOID);

HANDLE hRequestExitEvent = FALSE;

int main()
{
    HANDLE hThreads[2];
    DWORD dwThreadId;
    DWORD dwExitCode = 0;
    int i;

    hRequestExitEvent = CreateEvent(
        NULL, TRUE, FALSE, NULL);

    for (i=0; i<2; i++)
        MTVERIFY( hThreads[i] = CreateThread(NULL,
            0,
            ThreadFunc,
            (LPVOID)i,
            0,
            &dwThreadId )
        );

    // Wait around for awhile, make
    // sure the thread is running.
    Sleep(1000);

    SetEvent(hRequestExitEvent);//发送结束所有线程通知
    WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);//主线程等待所有线程结束

    for (i=0; i<2; i++)
        MTVERIFY( CloseHandle(hThreads[i]) );

    return EXIT_SUCCESS;
}


DWORD WINAPI ThreadFunc(LPVOID p)
{
    int i;
    int inside = 0;

    UNREFERENCED_PARAMETER(p);

    /* Seed the random-number generator */
    srand( (unsigned)time( NULL ) );

    for (i=0; i<1000000; i++)
    {
        double x = (double)(rand())/RAND_MAX;
        double y = (double)(rand())/RAND_MAX;
        if ( (x*x + y*y) <= 1.0 )
            inside++;
        if (WaitForSingleObject(hRequestExitEvent, 0) != WAIT_TIMEOUT)//被通知结束
        {
            printf("Received request to terminate\n");
            return (DWORD)-1;
        }
    }
    printf("PI = %.4g\n", (double)inside / i * 4);
    return 0;
}

文字版电子书-----请点击这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值