采用_beginthread/_beginthreadex函数创建多线程

windows多线程基础(5):使用_beginthreadex创建线程(C/C++ Runtime Library考虑) 标准CRT(C Runtime Library)问世于1970年,没有考虑到将CRT运行于多线程应用程序的问题。 在多线程环境中存在问题的C/C++运行期库变量和函数包括:error, _doserrno, strtok, strerror, asctime, gmtime,malloc等等。这些函数中都存在全局变量或者要访问全局变量(对于malloc来说,进程的堆也算是全全局的了),所 阅读详情

1、CRT简介:

CRT: (C Runtime Library)即C运行时库,是系统运行的基础,包含了c常用的函数集(如:printf,malloc,strcpy等),为运行main做了初始化环境变量、堆、io等资源,并在结束后清理。

在Windows环境下,VC提供的 C run-time library又分为动态运行时库、静态运行时库、多线程、单线程、调试版本(Debug)、发行版本(Release)等。

 开关

对应的库

版本

   /MD

MSVCRT.LIB

多线程DLL的Release版本

   /MDd

MSCVRTD.LIB

多线程DLL的Debug版本

   /MT

LIBCMT.LIB

多线程静态链接的Release版本

   /MTd

LIBCMTD.LIB

多线程静态链接的Debug版本

   /clr

MSVCMRT.LIB

托管代码和非托管代码混合

   /clr:pure

MSVCURT.LIB

纯托管代码

图1:编译器运行库设置(VS2008)

具体请参考MSDN:

ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_vccrt/html/a889fd39-807d-48f2-807f-81492612463f.htm

2、使用CRT的多线程函数集:两组

序号

函数名

功能

1

_beginthread()

创建一个新线程

2

_endthread()

结束一个线程的执行

3

_beginthreadex()

创建一个新线程

4

_endthreadex()

结束一个线程的执行

5

ResumeThread()

恢复线程的运行

6

SuspendThread()

挂起线程

7

GetExiCodeThread()

得到一个线程的退出码

8

WaitForSingleObject()

等待单个对象

9

WaitForMultipleObjects()

等待多个对象

3、两组函数的说明:

3.1、_beginthread和_endthread
该函数是C Runtime Library中的函数。其原型如下

unsigned long _beginthread(

void( __cdecl *start_address )( void * ),//线程函数的起始地址

unsigned stack_size,//堆栈大小,设置0为系统默认值

void *arglist );//传递给线程函数的参数,没有则为NULL

“该函数被认为是头脑简单的函数”,使用该函数导致无法有效的控制被创建线程,如不能在启动时将该线程挂起,无法为该线程设置优先权等。另外,无法利用这个Handle来等待该线程结束等操作。该函数是早期的C Runtime Library的产物,不提倡使用,后期的改良版本为_beginthreadex。
通过_beginthread启动的线程在应当通过调用_endthread结束,以保证清除与线程相关的资源。_endthread的原型为:

void _endthread(void);

 

3.2、_beginthreadex和_endthreadex
该函数是C Runtime Library中的一个函数,用标准C实现,相比_beginthread,_beginthreadex对线程控制更为有力(比前者多三个参数),是_beginthread的加强版。其原型为:

unsignedlong _beginthreadex(

void *security,//线程函数的安全描述符

unsigned stack_size,// 堆栈大小,设置0为系统默认值

unsigned ( __stdcall *start_address )( void * ),//线程函数的起始地址

void*arglist, //传递给线程函数的参数,没有则为NULL

unsignedinitflag,//初始状态,0为立即执行,CREATE_SUSPEND为创建后挂起

unsigned*thrdaddr );//指向一个32为的变量,存放线程标识符

该函数返回新线程的句柄,通过该句柄可实现对线程的控制。虽然,该函数是用标准C写的(即可不加修改就可以移植到其他系统执行),但是由于它与Windows系统有着紧密的联系(需要手动关闭该线程产生的Handle),因此实现时,往往需要包含windows.h。
通过_beginthreadex启动的线程通过调用_endthreadex做相关清理。该函数比较像CreateThread函数。

_endthreadex函数的原型为:

void _endthreadex(unsigned retVal);

关于这两组函数的详细区别请参考MSDN的说明:

Creates a thread.

uintptr_t _beginthread(

   void( *start_address )( void * ),

   unsigned stack_size,

   void *arglist

);

uintptr_t _beginthreadex(

   void *security,

   unsigned stack_size,

   unsigned ( *start_address )( void * ),

   void *arglist,

   unsigned initflag,

   unsigned *thrdaddr

);

Parameters

start_address

Start address of a routine that begins execution of a new thread.For _beginthread, the calling convention is either__cdecl or __clrcall; for _beginthreadex, it iseither __stdcall or __clrcall.

stack_size

Stack size for a new thread or 0.

arglist

Argument list to be passed to a new thread or NULL.

security

Pointer to a SECURITY_ATTRIBUTES structure that determines whetherthe returned handle can be inherited by child processes. If NULL, the handlecannot be inherited. Must be NULL for Windows 95 applications.

initflag

Initial state of a new thread (0 forrunning or CREATE_SUSPENDED for suspended); useResumeThread to execute the thread.

thrdaddr

Points to a 32-bit variable that receives the thread identifier.Might be NULL, in which case it is not used.

Return Value

If successful, each of these functions returns a handle to thenewly created thread; however, if the newly created thread exits too quickly, _beginthread might not return a valid handle (see thediscussion in the Remarks section). _beginthread returns -1L on an error, in which case errno is set to EAGAIN if thereare too many threads, to EINVAL if the argument isinvalid or the stack size is incorrect, or to EACCESin the case of insufficient resources (such as memory). _beginthreadexreturns 0 on an error, in which case errno and _doserrno are set.

If startaddress is NULL, the invalid parameter handler is invoked, asdescribed in Parameter Validation. If execution is allowed to continue, these functions set errno to EINVAL and return -1.

For more information about these and other return codes, see_doserrno, errno, _sys_errlist, and _sys_nerr.

For more information about uintptr_t,see Standard Types.

Remarks

The _beginthread function creates athread that begins execution of a routine at start_address.The routine at start_address must use the __cdecl calling convention and should have no returnvalue. When the thread returns from that routine, it is terminatedautomatically. For more information about threads, see Multithreading.

_beginthreadex resembles the Win32 CreateThread API more closely than _beginthread does. _beginthreadexdiffers from _beginthread in the following ways:

·        _beginthreadex has three additional parameters: initflag,security, and threadaddr.The new thread can be created in a suspended state, with a specified security(Windows NT only), and can be accessed using thrdaddr,which is the thread identifier.

·        The routine at start_address passed to _beginthreadexmust use the __stdcall calling convention and mustreturn a thread exit code.

·        _beginthreadex returns 0 on failure, rather than -1L.

·        A thread created with _beginthreadex is terminated by a call to _endthreadex.

The _beginthreadex function gives you morecontrol over how the thread is created than _beginthreaddoes. The _endthreadex function is also moreflexible. For example, with _beginthreadex, you canuse security information, set the initial state of the thread (running orsuspended), and get the thread identifier of the newly created thread. You arealso able to use the thread handle returned by _beginthreadexwith the synchronization APIs, which you cannot do with _beginthread.

It is safer to use _beginthreadex than _beginthread. If the thread generated by _beginthread exits quickly, the handle returned to thecaller of _beginthread might be invalid or, worse,point to another thread. However, the handle returned by _beginthreadexhas to be closed by the caller of _beginthreadex, soit is guaranteed to be a valid handle if _beginthreadexdid not return an error.

You can call _endthread or _endthreadex explicitly to terminate athread; however, _endthread or _endthreadexis called automatically when the thread returns from the routine passed as aparameter. Terminating a thread with a call to endthreador _endthreadex helps to ensure proper recovery ofresources allocated for the thread.

_endthread automatically closes the thread handle (whereas _endthreadex does not). Therefore, when using _beginthread and _endthread, donot explicitly close the thread handle by calling the Win32 CloseHandle API.This behavior differs from the Win32 ExitThread API.

Note:

For an executable file linked with Libcmt.lib , do not call the Win32 ExitThread API; this prevents the run-time system from reclaiming allocated resources. _endthread and _endthreadex reclaim allocated thread resources and then call ExitThread.

The operating system handles the allocation of the stack wheneither _beginthread or _beginthreadexis called; you do not need to pass the address of the thread stack to either ofthese functions. In addition, the stack_sizeargument can be 0, in which case the operating system uses the same value asthe stack specified for the main thread.

arglist is a parameter to be passed to the newly created thread.Typically it is the address of a data item, such as a character string. arglist can be NULL if it isnot needed, but _beginthread and _beginthreadex must be provided with some value to pass tothe new thread. All threads are terminated if any thread calls abort, exit, _exit, or ExitProcess.

The locale of the new thread is inherited from its parent thread.If per thread locale is enabled by a call to _configthreadlocale (eitherglobally or for new threads only), the thread can change its localeindependently from its parent by calling setlocaleor _wsetlocale. For more information, see Locale.

For mixed and pure code, _beginthreadand _beginthreadex both have two overloads, onetaking a native calling-convention function pointer, the other taking a __clrcall function pointer. The first overload is notapplication domain-safe and never will be. If you are writing mixed or purecode you must ensure that the new thread enters the correct application domainbefore it accesses managed resources. You can do this, for example, by usingcall_in_appdomain Function. The second overload is application domain-safe; thenewly created thread will always end up in the application domain of the callerof _beginthread or _beginthreadex.

Requirements

Routine

Required header

_beginthread

<process.h>

_beginthreadex

<process.h>

For more compatibility information, see Compatibility in theIntroduction.

Libraries

Multithreaded versions of the C run-time libraries only.

3.3、线程函数的定义:

_beginthread()和_beginthreadex()的线程执行函数的定义是不一样的。

对于_beginthread()创建的线程,其线程函数定义为:

void ThreadPro(void * pArguments );

对于_beginthreadex()创建的线程,其线程函数定义为:

unsigned __stdcallThreadFunc( void* pArguments )

4、注意事项:

(1)两者创建线程函数方式不同,_beginthreadex()的线程函数必须使用__stdcall调用方式,而且必须返回一个unsigned型的退出码。

(2)_beginthreadex()在创建线程失败时返回0,而_beginthread()在创建线程失败时返回-1,这一点在检测返回结果时必须注意。

(3)如果是调用_beginthread()创建线程,并相应地调用_endthread()结束线程时,系统将自动关闭线程句柄。而调用_beginthreadex()创建线程,并相应地调用_endthreadex()结束线程时,系统不能自动关闭线程句柄。

(4)由于_beginthread()创建线程参数比较简单,不能控制线程的初始启动状态,且不返回创建的线程句柄,也不能调用

WaitForSingleObject()/WaitForMultipleObjects()函数。所以一般不常用,而_beginthreadex()与CreatThread()函数比较相似。能方便控制线程。

 

5、多线程实例:

5.1、实例1:

实例说明:该实例主要使用_beginthread()函数,创建尽可能多的线程,知道系统不能再创建为止。注意实时数据的显示和参数的传递,如果想传递多个参数,则可以使用结构体。

主要函数如下:

//在.h文件中:

#define WM_ADD WM_USER+10//定义消息

void ThreadFunc1(void *pArg);//线程函数1:开始创建

void ThreadFunc2(void *pArg);//线程函数2:

LRESULT OnMyMsg(WPARAM, LPARAM);//消息函数  

 

//在.cpp文件中:

//全局变量,一般在cpp中定义,不要在.h定义,否则编译出错:变量重复定义

bool g_bRun = false;

long g_nCount = 0;

 

//开始按钮函数

void C_beginthreadDlg::OnBnClickedButtonRun()

{

    // TODO: 在此添加控件通知处理程序代码

    //创建线程:主要是用来创建执行创建线程池的线程

    if (_beginthread(ThreadFunc1,0,&m_hWnd) != -1 )

    {//成功

       GetDlgItem(IDC_BUTTON_RUN)->EnableWindow(FALSE);

    }

}

 

//创建线程池的线程函数

void ThreadFunc1(void *pArg)

{

    HWND *hWnd = (HWND*)pArg;//得到窗口句柄

    g_nCount= 0;//初始化变量

    g_bRun = true;

    while (g_bRun)

    {//开始创建尽可能多的线程

       if (_beginthread(ThreadFunc2,0,hWnd) == -1)

       {//失败则结束

           g_bRun= false;

           break;

       }

    }

    //退出

    ::SendMessage(*hWnd,WM_ADD,1,0); 

}

 

//线程函数

void ThreadFunc2(void *pArg)

{

    HWND *hWnd = (HWND*)pArg;

    g_nCount++;

    ::SendMessage(*hWnd,WM_ADD,0,g_nCount);//显示个数

    while(g_bRun)

    {

       Sleep(1000);

    }

}

 

// WM_ADD消息处理函数

LRESULT C_beginthreadDlg::OnMyMsg(WPARAM wParam, LPARAM lParam)

{

    if (wParam == 1)

    {//结束

       GetDlgItem(IDC_BUTTON_RUN)->EnableWindow(TRUE);

    }

    else

    {//显示更新

       m_nCount= g_nCount;

        UpdateData(FALSE);

    }

    return 0;

}

 

运行效果:

图2:实例1演示

工程源码下载地址:

http://download.youkuaiyun.com/detail/cbnotes/4902781

欢迎大家修改和指正。

注意事项:

(1)由于_beginthread()创建的线程结束后自动关闭线程句柄,所以不能使用WaitForSingleObject()/WaitForMultipleObjects()函数来同步。

(2)上面的程序中,先是创建了线程1(ThreadFunc1),再用该线程1来创建众多线程,而不是直接在OnBnClickedButtonRun()函数中创建众多线程,大家知道这是为什么吗?主要是为了能够实时显示创建的线程数目。如果直接在OnBnClickedButtonRun()函数中创建众多线程,主线程将一直处于while循环中,而不能及时处理消息,所以就不能实时显示创建的线程数目(不信的话大家可以试试)。

(3)注意线程函数参数的传递,和消息的发送。如果要传递多个参数,可以使用结构体传递。

5.2、实例2:

实例说明:该实例主要使用_beginthreadex()函数,多人合作(5人)共同完成一项任务,即平时大家说的分工合作,齐头并进。

主要函数如下:

//.h文件中

//声明线程处理函数

unsigned __stdcall ThreadFunc1( void*pArguments );//合作工作线程函数

unsigned __stdcall ThreadFunc2( void*pArguments );//检测工作完成线程函数

 

//为了传递多个参数,我采用结构体

struct threadInfo

{

    HWND hWnd;       //窗口句柄

    int  nOffset;    //偏移量

    int  nWidth;     //宽度

};

 

struct threadInfo2

{

    HWND   hWnd;           //窗口句柄

    HANDLE *phHandle;     //线程句柄指针

};

// 实现

protected:

    threadInfoInfo[5];

    HANDLE m_hThead[5];    //用于存储线程句柄

    HANDLE hThead;     //用于存储线程句柄

    unsigned  m_dwThreadID[5];//用于存储线程的ID

   threadInfo2Info2;

//在.cpp文件中

//开始按钮函数

void C_beginthreadexDlg::OnBnClickedButtonRun()

{

    // TODO: 在此添加控件通知处理程序代码

    //使能开始按钮:无效

    GetDlgItem(IDC_BUTTON_RUN)->EnableWindow(FALSE);

    CDC *dc = GetDC();

    CRect rt;

    GetClientRect(rt);

    dc->FillSolidRect(0,0,rt.Width(),200,RGB(240,240,240));//刷新背景

    ReleaseDC(dc);

    int nWidth = rt.Width()/5;

    //初始化线程的参数

    Info[0].hWnd = Info[1].hWnd = Info[2].hWnd = Info[3].hWnd = Info[4].hWnd = GetSafeHwnd();

    Info[0].nOffset = 0;Info[1].nOffset = nWidth;Info[2].nOffset= 2*nWidth;Info[3].nOffset = 3*nWidth;Info[4].nOffset= 4*nWidth;

    Info[0].nWidth = Info[1].nWidth = Info[2].nWidth = Info[3].nWidth = Info[4].nWidth = nWidth;

    //创建个模拟线程

    for (int i = 0;i<5;i++)

    {  

       m_hThead[i] = (HANDLE)_beginthreadex(NULL,0,ThreadFunc1,&Info[i],CREATE_SUSPENDED,&m_dwThreadID[i]); 

    }

    GetDlgItem(IDC_STATIC1)->SetWindowText("进行中...");

    //开始运行

    for (int i = 0;i<5;i++)

    {  

       ResumeThread(m_hThead[i]); 

    }

    //开始运行监测结果线程

    Info2.hWnd = m_hWnd;

    Info2.phHandle = m_hThead;

    hThead =(HANDLE)_beginthreadex(NULL,0,ThreadFunc2,&Info2,0,NULL);

}

 

//合作工作线程函数

unsigned __stdcall ThreadFunc1( void*pArguments )

{

    threadInfo*info = (threadInfo*)pArguments;

    CDC *dc = CWnd::FromHandle(info->hWnd)->GetDC();

    for (int i=info->nOffset;i<info->nOffset+info->nWidth;i++)

    {

       for (int j =0 ;j<200;j++)

       {  

           dc->SetPixel(i,j,RGB(0,0,0));

       }

    }

    DeleteObject(dc);

    return 0;

}

 

//等待所有的工作结束

unsigned __stdcall ThreadFunc2( void*pArguments )

{

    threadInfo2*info = (threadInfo2*)pArguments;

    //等待个线程中的一个完成

    DWORD dwRet = WaitForMultipleObjects(5,info->phHandle,TRUE,INFINITE);

    if (dwRet == WAIT_FAILED)

    {//出错啦

       ::SendMessage(info->hWnd,WM_GAMEOVER,1,0);

       return 0;

    }

    //完成结束

    ::SendMessage(info->hWnd,WM_GAMEOVER,0,0);

    return 0;

}

 

 

//消息处理函数

LRESULT C_beginthreadexDlg::OnGameOver(WPARAMwParam, LPARAMlParam)

{

    if (wParam ==1)

    {//出错

       GetDlgItem(IDC_STATIC1)->SetWindowText("出错啦!");

    }

    else

    {//成功

       //显示结果

       GetDlgItem(IDC_STATIC1)->SetWindowText("任务完成!");

       //闪动显示

       CDC *dc = GetDC();

       CRect rt;

       GetClientRect(rt);

       for (int i=0;i<8;i++)

       {

           dc->Draw3dRect(0,0,rt.Width(),200,RGB(240,240,240),RGB(240,240,240));//刷新背景

           dc->Draw3dRect(1,1,rt.Width()-1,199,RGB(240,240,240),RGB(240,240,240));//刷新背景

           Sleep(100);

           dc->Draw3dRect(0,0,rt.Width(),200,RGB(255,0,0),RGB(255,0,0));//刷新背景

           dc->Draw3dRect(1,1,rt.Width()-1,199,RGB(255,0,0),RGB(255,0,0));//刷新背景

           Sleep(100);

       }

       ReleaseDC(dc);

    }

    //关闭句柄

    for (int i=0;i<5;i++)

    {

       CloseHandle(m_hThead[i]);

    }

    CloseHandle(hThead);

    //使能开始按钮,以便可以开始下一次比赛

    GetDlgItem(IDC_BUTTON_RUN)->EnableWindow(TRUE);

    return 0;

}

运行效果:

工程源码下载地址:

http://download.youkuaiyun.com/detail/cbnotes/4905693

欢迎大家修改和指正。

注意事项:

(1)由于_beginthreadex()创建的线程结束后自动调用_endthreadex()函数,但是不会关闭线程句柄,所以必须手动关闭句柄,但能使用同步函数,如:

WaitForSingleObject()/WaitForMultipleObjects()函数来同步。

(2)通过该实例还可以稍加改进,就可以统计5个线程的各自的工作时间,并排序。欢迎大家多多练习。

(3)由_beginthreadex()函数创建线程,能灵和控制和管理线程,所以推荐使用该方式。

=================================================转载请标明出处,谢谢.http://blog.youkuaiyun.com/cbNotes

 

VC获取子线程入口函数的退出码(分别由CreateThread,_beginthread,_beginthreadex与AfxbeginThread 创建的子线程 ) 在 VC 编程中,若是涉及到多线程编程时,有时我们也需要根据情况获取子线程入口函数的退出码,以便根据具体的程序运行情况做相应的处理。        之前我在使用 VC 开发程序时,也遇到过需要获取子线程入口函数的退出码的问题,由于起初没有做过相似的程序,所以只会定义一个全局变量来根据情况,在子线程的入口函数里再为其赋予相应的值。虽然这也是一种方法,但根本不能决定根本的问题,而且若程序中的 阅读详情

相关推荐

windows C++多线程(四):_beginthread的使用

windows创建线程一般都使用CreateThread,该函数与CRT有冲突,尽量不要使用该函数,应该用_beginthread,结束线程用_endthread,这两个函数可以成套的使用。 使用这两个函数需要包含的头文件#include <process.h> _beginthread声明如下 ACRTIMP uintptr_t __cde...

琅嬛福地 3616

c++多线程之_beginthreadex

创建一个线程,具体用法查看代码 ,特别注意: 如果在代码中有使用标准C运行库中的函数时,尽量使用_beginthreadex()来代替CreateThread() 因为_beginthreadex在内部调用了CreateThread,在调用之前_beginthreadex做了很多的工作,从而使得它比CreateThread更安全。 例子一 #include <windows.h&g...

sinat_31608641的博客 5503

多线程编程在C++中的使用:_beginthread函数

注意,在实际的多线程编程中,还需要考虑线程的安全性、死锁等问题,并采取相应的措施进行处理。在C++中,可以使用互斥量(mutex)来实现线程之间的同步,并使用全局变量或线程局部存储(Thread Local Storage,TLS)来实现数据的共享。头文件,然后定义了线程函数,使用_beginthread函数创建线程,并在主函数中等待线程结束。在使用_beginthread函数创建线程之前,我们需要定义一个线程函数。一旦我们定义了线程函数,就可以使用_beginthread函数来创建线程。

CodeGu的博客 533

秒杀多线程第二篇 多线程第一次亲密接触 CreateThread与_beginthreadex本质区别

本文将带领你与多线程作第一次亲密接触,并深入分析CreateThread与_beginthreadex的本质区别,相信阅读本文后你能轻松的使用多线程并能流畅准确的回答CreateThread与_beginthreadex到底有什么区别,在实际的编程中到底应该使用CreateThread还是_beginthreadex? 使用多线程其实是非常容易的,下面这个程序的主线程会创建了一个子线程并等待...

huobengluantiao8 3585

一文带你看懂SAP-HANA的基本架构与原理

创作不易,希望大家一键三连支持!!!♥♥♥创作不易,希望大家一键三连支持!!!♥♥♥创作不易,希望大家一键三连支持!!!♥♥♥。

丷江南南的博客 5072

Java开发者必看:Apache PDFBox实现PDF数字签名完整指南(附源码)

本文为Java开发者提供了使用Apache PDFBox实现PDF数字签名的完整指南。详细介绍了从环境配置、核心原理到完整代码实现的全过程,涵盖证书管理、签名位置计算、性能优化及实际应用案例,并附有可直接复用的源码,帮助开发者高效集成PDF数字签名功能。

o1p2q3r的博客 339

采用_beginthread/_beginthreadex函数创建多线程两种方法

原帖: 1、CRT简介: CRT: (C Runtime Library)即C运行时库,是系统运行的基础,包含了c常用的函数集(如:printf,malloc,strcpy等),为运行main做了初始化环境变量、堆、io等资源,并在结束后清理。 在Windows环境下,VC提供的 C run-time library又分为动态运行时库、静态运行时库、多线程、单线程、调试版本(De

银冰冷月--学习笔记Blog 2296

AI与Agent赋能下的软件测试变革:面向未来测试工程师的工作方法论

AI Agent 软件测试 测试 software testing test

测试技师的自我修养 1230

VC.【转】采用_beginthread/_beginthreadex函数创建多线程

https://blog.youkuaiyun.com/cbnotes/article/details/8331632 还可以看这个网址的内容:【多线程】VC6使用_beginthread开启多线程的方法-技术宅的结界 - Powered by Discuz!.html(https://www.0xaa55.com/technews/201509/00000092.html) 网页内容保存: ...

weixin_30599769的博客 636

从零开始:使用Mask2Former训练你的专属图像分割数据集

本文详细介绍了如何使用Mask2Former训练自定义图像分割数据集,从环境配置、数据集准备到模型训练与优化。通过实战技巧和问题排查指南,帮助开发者高效完成从零开始的图像分割任务,特别适合需要处理自定义数据集的AI研究人员和工程师。

weixin_30566063的博客 638

NIDS——suricata(一)

NIDS——suricata环境安装和规则编写

weixin_58666006的博客 1273

Windows下C语言多线程函数_beginthread简单入门应用例子

有时候我们在Windows下使用C语言进行一些小工程编写的时候,需要用到并行程序设计的知识。但是一般情况下,我们学习C语言都很少接触并行程序的设计,对我而言,更加习惯使用Java的并行程序设计。最近学习需要,接触了C语言的多线程,网上搜索到的例子都不太容易理解,很多还是使用C++知识的,特别对于小白来说学习起来更加困难。因此在这里分享一下自己的学习心得,本文只涉及基本的C语言。

思维梯子 2万+

基本模型 PINNs : Physics Informed Neural Networks

系列最开始当然要提到很经典的文章 —— Physics-informed neural networks: A deep learning framework for solving forward and inverse problems involving nonlinear partial differential equations 。 这篇文章是布朗大学的助理教授Maziar Rais...

waitingwinter的博客 3万+

_beginthread, _beginthreadex

语法 uintptr_t _beginthread( // NATIVE CODE void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist ); uintptr_t _beginthread( // MANAGED CODE void( __clrcall *start_add...

wjh_init的博客 998

【FPGA教程案例49】控制案例1——基于FPGA的PID控制器verilog实现

PID控制器产生于1915年,PID控制律的概念最早是由LYAPIMOV提出的,到目前为止,PID控制器以及改进的PID控制器在工业控制领域里最为常见。PID控制器(比例-积分-微分控制器),由比例单元 P、积分单元 I 和微分单元 D 组成。通过Kp,Ki和Kd三个参数的设定。PID控制器主要适用于基本线性和动态特性不随时间变化的系统。图1为PID控制器的基本结构框图。PID控制器以其结构简单、稳定性好、工作可靠、调整方便而成为工业控制的主要技术之一。...

FPGA/MATLAB学习教程/源码/项目合作开发 4525

思维链:让AI更接近人类思维的技术

本文将探讨一种名为“思维链”的技术,它旨在让AI更接近人类思维。文章首先介绍了问题背景与核心概念,接着讲解了算法原理和数学模型,随后阐述了系统分析与架构设计,最后通过项目实战展示了思维链的实际应用,并提供了最佳实践和小结。思维链是一种旨在模拟人类思维过程的技术,它通过构建一系列相互关联的思维方式,实现对复杂问题的分析和解决。思维链算法是一种基于人类思维过程的人工智能算法,它通过构建一系列思维链,实现对问题的分析和解决。智能问答系统是一种常见的人工智能应用,它能够回答用户提出的各种问题。

AI天才研究院 942

C++多线程之_beginthread与_beginthreadex

标准C运行时库函数,需要包含头文件process.h。 创建线程 uintptr_t _beginthread( void (__cdecl *start_address)(void* fun),//线程执行函数,__cdecl unsigned stack_size, //线程的堆栈大小,0,默认大小(1M) void *arglist //线程执行函数的参数 ); uintptr_t

lxj434368832的博客 1046

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

_beginthreadex 和 _beginthread 的区别

一,函数原型: uintptr_t _beginthread(    void( *start_address )( void * ),    unsigned stack_size,    void *arglist ); uintptr_t _beginthreadex(    void *security,    unsigned stack_size,

人生代码,代码人生。。。 2774

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

关于_BEGINTHREADEX、_BEGINTHREAD和CREATETHREAD

说明:此文转自于http://www.cnblogs.com/whiteyun/archive/2011/06/02/2067742.html 在微软的 Programming Techniques 说明文件中有一句看似悲惨的警告: 警告:如果你在一个与 LIBCMT.LIB 链接的程序中调用 C runtime 函数, 你的线程就必须以 _beginthread() 启动之。不要使用

通过编程来表达自己的想法 1767

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

CreateThread, AfxBeginThread,_beginthread, _beginthreadex的区别

一、转载自: http://www.cnblogs.com/chuncn/archive/2009/03/08/1406096.htmlCreateThread是Windows的API函数(SDK函数的标准形式,直截了当的创建方式,任何场合都可以使用),提供操作系统级别的创建线程的操作,且仅限于工作者线程。不调用MFC和RTL的函数时,可以用CreateThread,其它情况不要轻易。在使

miyunhong的专栏 2343

【C++】多线程之_beginthread与_beginthreadex

标准C运行时库函数,需要包含头文件process.h。

Hi, Boy 2455

CreateThread, AfxBeginThread,_beginthread, _beginthreadex线程函数区别

转自:http://hi.baidu.com/laoyang1018/item/e86b4aa8d28fc23c030a4dd7 瑶瑶按: 创建线程好几个函数可以使用,可是它们有什么区别,适用于什么情况呢? 参考了一些资料,写得都挺好的,这里做一些摘抄和整合。 【参考1】CreateThread, AfxBeginThread,_beginthread, _beginthreade

acsder2010413的专栏 981

C++多线程——_beginthread()和_beginthreadex

1.函数原型及参数说明 unsigned long _beginthread( void(_cdecl *start_address)(void *), //声明为void (*start_address)(void *)形式 unsigned stack_size, //是线程堆栈大小,一般默认为0 void *arglist //向线程传递的参数,一般为结构体 ); unsig

xuanyin235的专栏 1万+

CreateThread()、_beginthread() _beginthreadex() 联系与区别

原型: uintptr_t _beginthread( void( *start_address )( void * ), //新线程起始地址 unsigned stack_size, //堆栈大小 void *arglist //传递给新线程参数列表 ); unsigned long _beginthreadex( void *secu

JINKAI 1461
上一篇: 在VS2008的解决方案中添加多个现有工程的方法
下一篇: MFC多线程的创建,包括工作线程和用户界面线程
cbNotes
博客等级 码龄14年 295粉丝 57原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值