多线程(198)

咋说呢,一直以来虽然知道_beginthreadex比较好。但是想起55用CreateThread,还是有点余悸。

先看段原话

有些CRT的函数象malloc(), fopen(), _open(), strtok(), ctime(), 或localtime()等函数需要专门的线程局部存储的数据块,
这个数据块通常需要在创建线程的时候就建立,如果使用CreateThread,这个数据块就没有建立,然后会怎样呢?
在这样的线程中还是可以使用这些函数而且没有出错,实际上函数发现这个数据块的指针为空时,会自己建立一个,
然后将其与线程联系在一起,这意味着如果你用CreateThread来创建线程,然后使用这样的函数,
会有一块内存在不知不觉中创建,遗憾的是,这些函数并不将其删除,而CreateThreadExitThread也无法知道这件事,
于是就会有Memory Leak,在线程频繁启动的软件中(比如某些服务器软件),迟早会让系统的内存资源耗尽!


说白了:如果多线程里面有CRT函数,最好使用_beginthread _beginthreadex AfxBeginThread(这个函数内部调用_beginthreadex创建处理的CWinThread专门的UI线程,可以通过发送接收message)

上面四个线程都有相应的ExitThread或_endthread;当然这些函数必须放入线程函数中。

共同点:

共同的毛病1:

虽然:在线程被创建成功后,都可以用WaitForSingleObject( hThread, INFINITE );来等待线程结束。
但是这是不准的:一些begin函数本身就有CloseHandle了(如:_beginthread),再加上一些代码的CloseHandle
所以无法正确知道线程的计数到底是在哪个时候被置为0,而且被置为0也不一定会是线程退出。
再说执行完线程函数后,beging函数本身有许多代码要执行。
也就是说,最好不要这么等待线程结束,最好给个事件、原子等放在线程函数末尾,来判断线程是否结束。

共同的毛病2:

如果在线程函数中调用退出函数,是会立即退出的。
也就是说连执行线程函数中,定义类的析构函数都来不及,就会直接退出线程返回,
如果那个类有析构有内存释放的话就糟糕了,会出现内存泄漏的。
也就是说,最好不要用退出线程函数来退出线程,用return自然返回是最好的。

内存释放:

  • 内存释放这里也有个共同点; 创建线程后直接CloseHandle是可以的,这样的线程对象,在函数运行完了就自动释放(就算是_beginthread等有自释放代码的类型也同样适用)

AfxBeginThread会自动CloseHandle;相应endthread函数也有CloseHandle代码
_beginthread会自动CloseHandle;相应endthread函数也有CloseHandle代码
_beginthreadex必须手动CloseHandle
CreateThread必须手动CloseHandle

比较:

AfxBeginThread创建的线程比较庞大,一般的后台运行线程是没必要的
CreateThread创建的线程无法使用CRT函数
_beginthread创建的线程可以使用CRT函数,但引用官方的话来说:“使用 _beginthreadex 比 _beginthread 更为安全”;

// //