【C语言】Windows下的多线程编程

您所在的位置:网站首页 c语言的多线程编程 【C语言】Windows下的多线程编程

【C语言】Windows下的多线程编程

2024-07-03 23:08| 来源: 网络整理| 查看: 265

_beginthread和_beginthreadex是Windows下创建线程的函数。 结束线程函数_endthread和_endthreadex。

主线程结束了,子线程也会结束。

_beginthread函数原型 /** \brief 创建一个线程 * * \param start_address 新线程的起始地址 ,指向新线程调用的函数的起始地址 * \param stack_size 新线程的堆栈大小,可以为0 * \param arglist 传递给线程的参数列表,无参数时为NULL,多参数的时候可以传入结构体 * \return 成功,函数将会返回一个新线程的句柄 * 失败_beginthread将返回-1 * 如 th1 = (HANDLE)_beginthread(Thread1, 0, NULL); * */ uintptr_t _beginthread(void(*start_address)(void*), unsigned stack_size, void* arglist);

另uintptr_t的类型为unsigned long long

typedef unsigned __int64 uintptr_t; _beginthreadex函数原型 /** \brief 创建一个线程 * * \param security 安全属性, 为 NULL时表示默认安全性 * \param stack_size 新线程的堆栈大小,一般默认为0 * \param start_address 指定线程函数,也就是线程调用执行的函数地址 * \param arglist 传递给线程的参数列表,无参数时为 NULL,多参数的时候可以传入结构体 * \param initflag 新线程的初始状态,0表示立即执行,CREATE_SUSPENDED表示创建之后挂起 * \param threaddr 指向接收线程标识符的 32 位变量。 如果是 NULL ,则不使用 * \return 成功,函数将会返回一个新线程的句柄 * 发生错误时, _beginthreadex 返回 0 并设置 errno 和 _doserrno * */ uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned(_stdcall* start_address)(void*), void* argilist, unsigned initflag, unsigned* threaddr); _endthread函数原型 /** \brief 终止线程 * * \param 无 * \return 无 * */ void _endthread(void);

注意:_endthread 会自动关闭线程句柄。 (该行为与 Win32 ExitThread API 不同。) 因此,当你使用 _beginthread 和 _endthread 时,不要通过调用 Win32 CloseHandle API 来显式关闭线程句柄。

_endthreadex函数原型 /** \brief 终止线程 * * \param retval 线程退出代码 * \return 无 * */ void _endthreadex(unsigned retval);

注意: _endthreadex 不会关闭线程句柄。 因此,当你使用 _beginthreadex 和 _endthreadex时,必须通过调用 Win32 CloseHandle API 来关闭线程句柄。

示例1 #include #include #include /* 线程函数声明 */ void Thread1(void*); void Thread2(void*); //unsigned int __stdcall Thread1ex(void*); //unsigned int __stdcall Thread2ex(void*); /* 线程句柄 */ HANDLE h1, h2; /* 线程共享内存 */ volatile int i = 0; /* 主线程 */ int main() { /* 创建线程 */ h1 = (HANDLE)_beginthread(Thread1, 0, NULL);//线程1 h2 = (HANDLE)_beginthread(Thread2, 0, NULL);//线程2 //h1 = (HANDLE)_beginthreadex(NULL, 0, Thread1ex, NULL, 0, NULL); //h2 = (HANDLE)_beginthreadex(NULL, 0, Thread2ex, NULL, 0, NULL); WaitForSingleObject(h1, INFINITE);//等待线程1结束 WaitForSingleObject(h2, INFINITE);//等待线程2结束 //system("pause"); printf("主线程结束\n"); return 0; } /* 线程1 */ void Thread1(void* arg) { while (1) { printf("Thread1\n"); Sleep(100); } } /* 线程2 */ void Thread2(void* arg) { while (1) { printf("Thread2\n"); Sleep(100); } } ///* 线程1 */ //unsigned int __stdcall Thread1ex(void* arg) //{ // while (1) // { // printf("Thread1\n"); // Sleep(100); // } //} // // ///* 线程2*/ //unsigned int __stdcall Thread2ex(void* arg) //{ // while (1) // { // printf("Thread2\n"); // Sleep(100); // } //}

输出结果 在这里插入图片描述

WaitForSingleObject /** \brief 等待函数 – 使线程进入等待状态,直到指定的内核对象被触发。 * * \param hHandle 要等待的内核对象 * \param dwMilliseconds 最长等待的时间,以毫秒为单位;传入0就立即返回,传入INFINITE表示无限等待 * \return 在指定的时间内对象被触发,函数返回WAIT_OBJECT_0 * 超过最长等待时间对象仍未被触发返回WAIT_TIMEOUT。传入参数有错误将返回WAIT_FAILED * */ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);

WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。

对应的还有一个函数

WaitForMultipleObjects /** \brief 等待函数 – 使线程进入等待状态,直到指定的内核对象被触发。 * * \param nCount lpHandles指向的数组中的对象句柄数。对象句柄的最大数量为MAXIMUM_WAIT_OBJECTS。此参数不能为零 * \param lpHandles 一组对象句柄。该数组可以包含不同类型对象的句柄。它可能不包含同一句柄的多个副本 * 如果其中一个句柄在等待仍处于暂挂状态时关闭,则该函数的行为未定义 * \param bWaitAll 如果此参数为TRUE,则在lpHandles数组中的所有对象的状态发出信号时,该函数返回。如果为FALSE,则当任何一个对象的状态设置为信号时,该函数返回 在后一种情况下,返回值表示其状态导致函数返回的对象。 * \param dwMilliseconds 最长等待的时间,以毫秒为单位;传入0就立即返回,传入INFINITE表示无限等待 * \return 返回WAIT_OBJECT_0则返回值表明所有指定对象的状态信号 * 超过最长等待时间对象仍未被触发返回WAIT_TIMEOUT。传入参数有错误将返回WAIT_FAILED * */ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds ); 示例2

线程1与线程2通过共享内存来通讯。

#include #include #include /* 线程函数声明 */ //void Thread1(void*); //void Thread2(void*); unsigned int __stdcall Thread1ex(void*); unsigned int __stdcall Thread2ex(void*); /* 线程句柄 */ HANDLE h1, h2; /* 线程共享内存 */ volatile int i = 0; /* 主线程 */ int main() { /* 创建线程 */ //h1 = (HANDLE)_beginthread(Thread1, 0, NULL);//线程1 //h2 = (HANDLE)_beginthread(Thread2, 0, NULL);//线程2 h1 = (HANDLE)_beginthreadex(NULL, 0, Thread1ex, NULL, 0, NULL); h2 = (HANDLE)_beginthreadex(NULL, 0, Thread2ex, NULL, 0, NULL); while (1) { printf("Main Thread\n"); Sleep(100); } system("pause"); return 0; } ///* 线程1 */ //void Thread1(void* arg) //{ // while (1) // { // printf("Thread1\n"); // Sleep(100); // } //} // // ///* 线程2 */ //void Thread2(void* arg) //{ // while (1) // { // printf("Thread2\n"); // Sleep(100); // } //} /* 线程1 */ unsigned int __stdcall Thread1ex(void* arg) { while (1) { i++; Sleep(100); } } /* 线程2*/ unsigned int __stdcall Thread2ex(void* arg) { while (1) { printf("i = %d\n", i); Sleep(100); } }

输出结果 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3