- 浏览: 3449038 次
- 性别:
- 来自: 苏州
文章分类
最新评论
-
sonichy:
Qt5改动很多,要改改了。
基于QItemDelegate的例子1 SpinBoxDelegate -
我的主页6:
楼主,2.2子查询的分页方式:SELECT * FROM ar ...
Mysql 分页语句Limit用法 -
liguoqi:
非常感谢楼主的用心指导,工具以及图片例子都提供了 赞!
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载 -
liguoqi:
问下这个图片怎么解压损坏呀
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载 -
liguoqi:
楼主讲解的非常详细,还附带工具和图片例子,非常感谢
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载
_beginThreadex创建多线程解读
一、需要的头文件支持
#include <process.h> // for _beginthread()
需要的设置:ProjectàSetting-->C/C++-->User run-time library 选择Debug Multithreaded 或者Multithreaded。即使用: MT或MTD。
源码如下:
- #include <stdio.h>
- #include <string> // for STL string class
- #include <windows.h> // for HANDLE
- #include <process.h> // for _beginthread()
- using namespace std;
- class ThreadX
- {
- private:
- int loopStart;
- int loopEnd;
- int dispFrequency;
- public:
- string threadName;
- ThreadX( int startValue, int endValue, int frequency )
- {
- loopStart = startValue;
- loopEnd = endValue;
- dispFrequency = frequency;
- }
- static unsigned __stdcall ThreadStaticEntryPoint(void * pThis)
- {
- ThreadX * pthX = (ThreadX*)pThis; // the tricky cast
- pthX->ThreadEntryPoint(); // now call the true entry-point-function
- return 1; // the thread exit code
- }
- void ThreadEntryPoint()
- {
- for (int i = loopStart; i <= loopEnd; ++i)
- {
- if (i % dispFrequency == 0)
- {
- printf( "%s: i = %d\n", threadName.c_str(), i );
- }
- }
- printf( "%s thread terminating\n", threadName.c_str() );
- }
- };
- int main()
- {
- ThreadX * o1 = new ThreadX( 0, 1, 2000 );
- HANDLE hth1;
- unsigned uiThread1ID;
- hth1 = (HANDLE)_beginthreadex( NULL, // security
- 0, // stack size
- ThreadX::ThreadStaticEntryPoint,
- o1, // arg list
- CREATE_SUSPENDED, // so we can later call ResumeThread()
- &uiThread1ID );
- if ( hth1 == 0 )
- printf("Failed to create thread 1\n");
- DWORD dwExitCode;
- GetExitCodeThread( hth1, &dwExitCode ); // should be STILL_ACTIVE = 0x00000103 = 259
- printf( "initial thread 1 exit code = %u\n", dwExitCode );
- o1->threadName = "t1";
- ThreadX * o2 = new ThreadX( -100000, 0, 2000 );
- HANDLE hth2;
- unsigned uiThread2ID;
- hth2 = (HANDLE)_beginthreadex( NULL, // security
- 0, // stack size
- ThreadX::ThreadStaticEntryPoint,
- o2, // arg list
- CREATE_SUSPENDED, // so we can later call ResumeThread()
- &uiThread2ID );
- if ( hth2 == 0 )
- printf("Failed to create thread 2\n");
- GetExitCodeThread( hth2, &dwExitCode ); // should be STILL_ACTIVE = 0x00000103 = 259
- printf( "initial thread 2 exit code = %u\n", dwExitCode );
- o2->threadName = "t2";
- ResumeThread( hth1 ); // serves the purpose of Jaeschke's t1->Start()
- ResumeThread( hth2 );
- WaitForSingleObject( hth1, INFINITE );
- WaitForSingleObject( hth2, INFINITE );
- GetExitCodeThread( hth1, &dwExitCode );
- printf( "thread 1 exited with code %u\n", dwExitCode );
- GetExitCodeThread( hth2, &dwExitCode );
- printf( "thread 2 exited with code %u\n", dwExitCode );
- CloseHandle( hth1 );
- CloseHandle( hth2 );
- delete o1;
- o1 = NULL;
- delete o2;
- o2 = NULL;
- printf("Primary thread terminating.\n");
- return 0;
- }
二、解释
(1)如果你正在编写C/C++代码,决不应该调用CreateThread。相反,应该使用VisualC++运行期库函数_beginthreadex,退出也应该使用_endthreadex。如果不使用Microsoft的VisualC++编译器,你的编译器供应商有它自己的CreateThread替代函数。不管这个替代函数是什么,你都必须使用。
(2)因为_beginthreadex和_endthreadex是CRT线程函数,所以必须注意编译选项runtimelibaray的选择,使用MT或MTD。[MultiThreaded , Debug MultiThreaded]。
(3)_beginthreadex函数的参数列表与CreateThread函数的参数列表是相同的,但是参数名和类型并不完全相同。这是因为Microsoft的C/C++运行期库的开发小组认为,C/C++运行期函数不应该对Windows数据类型有任何依赖。_beginthreadex函数也像CreateThread那样,返回新创建的线程的句柄。
下面是关于_beginthreadex的一些要点:
1)每个线程均获得由C/C++运行期库的堆栈分配的自己的tiddata内存结构。(tiddata结构位于Mtdll.h文件中的VisualC++源代码中)。
2)传递给_beginthreadex的线程函数的地址保存在tiddata内存块中。传递给该函数的参数也保存在该数据块中。
3)_beginthreadex确实从内部调用CreateThread,因为这是操作系统了解如何创建新线程的唯一方法。
4)当调用CreatetThread时,它被告知通过调用_threadstartex而不是pfnStartAddr来启动执行新线程。还有,传递给线程函数的参数是tiddata结构而不是pvParam的地址。
5)如果一切顺利,就会像CreateThread那样返回线程句柄。如果任何操作失败了,便返回NULL。
(4)_endthreadex的一些要点:
C运行期库的_getptd函数内部调用操作系统的TlsGetValue函数,该函数负责检索调用线程的tiddata内存块的地址。
然后该数据块被释放,而操作系统的ExitThread函数被调用,以便真正撤消该线程。当然,退出代码要正确地设置和传递。
(5)虽然也提供了简化版的的_beginthread和_endthread,但是可控制性太差,所以一般不使用。
(6)线程handle因为是内核对象,所以需要在最后closehandle。
(7)更多的API:
HANDLE GetCurrentProcess();
HANDLE GetCurrentThread();
DWORD GetCurrentProcessId();
DWORD GetCurrentThreadId()。
DWORD SetThreadIdealProcessor(HANDLE hThread,DWORDdwIdealProcessor);
BOOL SetThreadPriority(HANDLE hThread,int nPriority);
BOOL SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
BOOL GetThreadContext(HANDLE hThread,PCONTEXTpContext);
BOOL SwitchToThread();
三、注意
(1)C++主线程的终止,同时也会终止所有主线程创建的子线程,不管子线程有没有执行完毕。所以上面的代码中如果不调用WaitForSingleObject,则2个子线程t1和t2可能并没有执行完毕或根本没有执行。
(2)如果某线程挂起,然后有调用WaitForSingleObject等待该线程,就会导致死锁。所以上面的代码如果不调用resumethread,则会死锁。
四、为什么用_beginthreadex而不是CreateThread?
为什么要用C运行时库的_beginthreadex代替操作系统的CreateThread来创建线程?
来源自自1999年7月MSJ杂志的《Win32 Q&A》栏目
你也许会说我一直用CreateThread来创建线程,一直都工作得好好的,为什么要用_beginthreadex来代替CreateThread,下面让我来告诉你为什么。
回答一个问题可以有两种方式,一种是简单的,一种是复杂的。
如果你不愿意看下面的长篇大论,那我可以告诉你简单的答案:_beginthreadex在内部调用了CreateThread,在调用之前_beginthreadex做了很多的工作,从而使得它比CreateThread更安全。
转载一部分,自己总结了一部分。
发表评论
-
C++ 实现把非静态成员函数作为回调函数(非static)
2012-11-16 10:10 14595众所周知,C++的类成员函数不能像普通函数那样用于回调,因 ... -
【转】windows多线程CreateThread与_beginthreadex本质区别
2012-11-15 14:40 13822本文将带领你与多线程作第一次亲密接触,并深入分析Crea ... -
ostringstream 的清空数据方法
2012-09-27 15:28 19401关于C++中 <sstream>中ostrings ... -
输入参数和输出参数
2012-09-26 10:43 36671. 输入参数,是函数的调用者,传递给函数的实现者,对函 ... -
ofstream、ifstream、fstream
2012-09-23 19:23 2923学习一下C++的文件流: ofstream是从内 ... -
将ostream 对象转换成字符串流输出
2012-09-22 10:47 8601将ostream 对象转换成字符串流输出 因为项目中需 ... -
sstream和strstream以及fstream
2012-09-22 10:38 4456在C++有两种字符串流,也称为数组I/O流,一种在sstre ... -
字符串流 ostrstream 和 istrstream
2012-09-22 10:28 7928ostrstream类流 /*ostrst ... -
将有格式的int解析成float
2012-09-20 18:10 2309因项目中有一个需求:将采集到所有short int 转换成fl ... -
回调函数测试例子
2012-09-29 14:15 4329回调函数就是一个通过函数指针调用的函数。如果你把函数的指 ... -
fatal error C1083: Cannot open include file: 'iostream.h': No such file or dire
2012-09-20 17:19 6446错误: fatal error C1083: Cannot o ... -
C++中类的声明
2012-08-29 16:28 6945可以声明一个类而不定义它 class Sc ... -
only static const integral data members can be initialized within a class
2012-06-28 11:40 2746翻译一下:只有静态整型常量数据成员能在类中初始化 ... -
fstream与 C 风格(例如fread 和 fwrite )两种读写文件方法的效率比较
2012-06-27 17:21 20992我觉得作者写的挺好,评论也写的很对。 目前我的项目 ... -
C/C++快速写入类结构对象进入文件
2012-06-19 10:38 0void QObject::deleteLater() { ... -
C语言文件操作函数大全
2012-06-18 13:54 2384C语言文件操作函数大 ... -
C++ 动态申请数组
2012-06-09 00:05 6708方法1、C++使用vector方便 ... -
VC++动态链接库(DLL)编程深入浅出(ZZ)
2012-06-08 10:06 24471.概论 先来阐述一下DLL(Dynamic Link ... -
C++中的头文件和源文件
2012-05-09 14:54 6623一、C++编译模式 通常 ... -
C语言下,获取文件信息
2012-05-08 15:07 6694C语言下,如何获取文件的生成时间,日期和文件大小等文件信息。 ...
相关推荐
实现多人聊天室需要使用 Windows Socket 编程、多线程编程和链表实现客户端连接管理。同时,需要注意线程安全和资源管理。 知识点: * Windows Socket 编程 * 多线程编程 * 网络编程 * 链表实现客户端连接管理 * ...
### 基于UDP的Socket程序:多线程操作,Windows下的C语言实现 #### 概述 本文将深入分析一个使用C语言在Windows环境下编写的UDP Socket程序,该程序支持多线程并发操作,实现了数据包的发送与接收功能。通过对给定...
### C语言多线程编程教程 POSIX线程库 #### 多线程概念介绍 多线程编程是指在单个程序中同时执行多个线程的技术,其中每个线程都是程序执行的独立路径。在C语言中,多线程编程能够使开发者在不同的线程中并行执行...
c语言多进程多线程编程c语言多进程多线程编程c语言多进程多线程编程c语言多进程多线程编程
在这个“c语言多线程操作”的项目中,开发者利用了VC++6.0的环境,这是一个早期的集成开发环境(IDE),它包含了Microsoft的Windows API,这个API提供了创建和管理线程的功能。 多线程是一种编程模型,允许一个应用...
Windows 及 Linux 环境下的 C 语言多线程编程总结 本文总结了 Windows 及 Linux 环境下的 C 语言多线程编程的相关知识点。首先,讨论了在 Windows 环境下的 C 语言多线程编程,包括 `_beginthread()` 函数的使用、...
总的来说,这个压缩包中的项目提供了关于C语言编程、异或加密算法和Windows平台下多线程技术的实际应用示例。对于想深入学习这些领域的开发者,这是一个很好的实践案例,可以从中学到如何将理论知识应用于实际编程中...
6. 多线程编程: - CreateThread函数用于创建新线程,文档中展示了如何为每个接受的客户端连接创建一个线程。 - 线程函数ThreadProc接受一个void*类型的参数,这里是一个socket句柄,用于从特定客户端接收和发送...
本文将深入探讨如何在Windows操作系统下,利用Microsoft Visual Studio 2015(VS2015)进行C语言多线程程序的开发。我们将关注三个核心部分:线程创建、线程同步以及线程通信。 首先,我们要引入Windows API中的...
Linux下C语言应用编程》深入浅出地讲解了Linux下C应用程序开发所需的基本工具、知识和技巧,主要包括:开发工具的使用和技巧、文件I/O编程、多进程编程、进程间通信、多线程编程、网络编程等内容。可以让读者轻松、...
在C语言中,多线程编程是实现并发执行任务的一种方式。这允许程序同时执行多个独立的任务,提高系统效率和响应性。在这个“C语言使用多线程例子”中,我们将探讨如何使用Windows API中的`CreateThread`函数来创建...
在Windows环境下进行C语言网络编程,首先需要理解的是,C语言本身并不直接支持网络功能,而是需要借助操作系统提供的API函数来实现。Windows操作系统提供了丰富的API接口供开发者使用,特别是对于网络编程,我们可以...
在Windows环境下,使用C语言进行网络编程,尤其是构建多人...综上所述,这个C语言程序展示了如何在Windows环境下,利用Winsock库创建一个简单的TCP服务器,支持多线程处理客户端连接,实现一个基本的多人聊天室功能。
总的来说,通过这个压缩包,你可以了解到C语言在Windows环境下实现多线程编程的方法,以及如何使用Mutex、Semaphore和Event来实现线程间的同步和通信。这对于提升你的Windows系统级编程能力,尤其是理解和处理并发...
此实例在windows 10系统上可以成功运行,可以修改一下,在linux上也可以运行,思路都是一样的。 说明:这个是个图书馆案例,默认100个座位,生产者与消费者各2个线程 (修改:加锁)
在Windows 10环境下使用Visual Studio 2019(VS2019)进行C语言的多线程编程,需要进行一系列配置步骤。这里主要介绍如何配置VS2019以便支持C语言的多线程功能,以及解决在配置过程中可能遇到的问题。 首先,我们...
#### 在IBM大型机的z/OS环境下的C语言多任务编程原理 本文旨在深入探讨IBM大型机环境下(特别是z/OS操作系统)利用C语言进行多任务编程的技术细节与实践方法。在IBM大型机上运行的z/OS系统为开发人员提供了一个强大...
10. **多线程编程** - Windows C编程中,多线程是实现并发操作的重要手段,可以使用`CreateThread()`函数创建新线程,`WaitForSingleObject()`等待线程完成,以及`ExitThread()`终止线程。 以上就是基于Windows...
7. **性能优化**:在实际应用中,可能需要考虑性能优化,例如使用非阻塞I/O模式,避免在网络繁忙时造成程序卡死,或者使用多线程处理发送和接收,提高并发能力。 通过理解和实践这些知识点,你将能够构建起一个基本...