createthread函数,C++多线程函数CreateThread如何使用?
createthread函数,C++多线程函数CreateThread如何使用?详细介绍
本文目录一览: (C++多线程问题)CreateThread()函数问题
关于六个参数:第一个是所创线程的安全属性,多设置为NULL; 第二个是所创线程堆栈的大小,多设为0; 第三个是你创建的线程的地址;(此处应为你的线程函数的函数名) 第四个是传递给你的线程函数的参数; 第五个是表示你创建的线程是否立即执行,设为0则立即执行; 第六个则是你创建线程的ID号,设为NULL就行。关于线程你要知道他有一个对应的线程函数,你创建线程后即执行你的函数(若你指定第五个参数为0立即执行,所执行的函数即为第三个参数)对于二楼他设置了一个等待,若无此等待可能会导致创建线程的函数已经退出,而你的线程却还在运行。
(1)LPTHREAD_START_ROUTINE lpStartAddress 指定了线程函数的起始地址,新建线程将从此地址开始执行,直到return语句返回,把控制权交给操作系统。
(2)LPVOID lpParameter 则是传递给线程函数的参数,也即传递给(1)中指定的线程函数的地址。
以下是一个例子:创建线程后,将转到线程函数执行,遇到return语句后返回到main函数。
#include
#include
using namespace std;
/*ThreadProc为LPTHREAD_START_ROUTINE lpStartAddress
*参数指定的线程函数.lpParam则是LPVOID lpParameter指
*定的传递给线程函数的参数*/
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
for (int i = 0;i < 20;++i)
{
cout << "I am from a thread,count = " << i <
<endl;
}
return 0;
}
int main()
{
HANDLE hThread;
DWORD dwThreadID;
hThread = ::CreateThread(
NULL,
NULL,
ThreadProc, // 线程入口地址
NULL,
0,
&dwThreadID);
::WaitForSingleObject(hThread,INFINITE);
::CloseHandle(hThread);
return 0;
}
一、Windows API函数。该函数在主线程的基础上创建一个新线程。微软在Windows API中提供了建立新的线程的函数CreateThread。
二、CreateThread将在主线程的基础上创建一个新线程,大致做如下步骤:
1.在内核对象中分配一个线程标识/句柄,可供管理,由CreateThread返回
2.把线程退出码置为STILL_ACTIVE,把线程挂起计数置1
3.分配context结构
4.分配两页的物理存储以准备栈,保护页设置为PAGE_READWRITE,第2页设为PAGE_GUARD
5.lpStartAddr和lpvThread值被放在栈顶,使它们成为传送给StartOfThread的参数
6.把context结构的栈指针指向栈顶(第5步)指令指针指向startOfThread函数
三、MSDN中CreateThread原型:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD
SIZE_T dwStackSize,//initialstacksize
LPTHREAD_START_ROUTINE lpStartAddress,//threadfunction
LPVOID lpParameter,//threadargument
DWORD dwCreationFlags,//creationoption
LPDWORD lpThreadId//threadidentifier
)
processthreadsapi.h中CreateThread原型:
WINBASEAPI
_Ret_maybenull_
HANDLE
WINAPI
CreateThread(
_In_opt_LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_SIZE_T dwStackSize,
_In_LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt___drv_aliasesMemLPVOID lpParameter,
_In_DWORD dwCreationFlags,
_Out_opt_LPDWORD lpThreadId
);
四、示例:
</endl;
Thread的线程相关函数
CreateThread()函数用于创建线程;返回值为所创建线程的句柄。ExitThread()函数用于结束本线程。SuspendThread()函数用于挂起指定的线程。ResumeThread()函数递减指定线程的挂起计数,挂起计数为0时,线程恢复执行。 pthread_create()函数用于创建线程。返回值为创建线程失败时的错误码;若返回0,表示线程创建成功。 pthread_exit()函数用于结束当前线程。 pthread_join()函数用于等待线程运行结束。 UNIX International 线程thr_create()函数用于创建线程。 thr_join()函数用于等待线程运行结束。 thr_suspend()函数用于挂起线程。 thr_continue()函数用于恢复被挂起的线程。 thr_exit()函数用于结束当前线程。 thr_self()函数用于返回当前线程的线程标识符。 thrd_create()函数用于创建线程。 thrd_join()函数用于等待线程运行结束。 thrd_exit()函数用于结束当前线程。 thrd_current()函数用于返回当前线程的线程标识符。 thrd_sleep()函数用于让线程休眠指定时间。 std::thread::thread(),构造函数,用于创建线程。 std::thread::join(),用于等待线程运行结束。 std::thread::detach(),用于让线程不受句柄控制。 std::thread::swap(),用于交换两个线程。 std::thread::get_id(),用于获得线程ID号。 std::thread::joinable(),用于判断线程是否可等待。 std::thread::native_handle(),用于获得与操作系统相关的原生线程句柄。 start(),启动线程。join(),等待线程运行完毕。sleep(),让线程休眠一段时间。setPriority(),设置线程优先级。
c# 用Windows API CreateThread函数如何创建的线程
微软在Windows API中提供了建立新的线程的函数CreateThread。
概述: 当使用CreateProcess调用时,系统将创建一个进程和一个主线程。CreateThread将在主线程的基础上创建一个新线程,大致做如下步骤:
在内核对象中分配一个线程标识/句柄,可供管理,由CreateThread返回
把线程退出码置为STILL_ACTIVE,把线程挂起计数置1
分配context结构
分配两页的物理存储以准备栈,保护页设置为PAGE_READWRITE,第2页设为PAGE_GUARD
lpStartAddr和lpvThread值被放在栈顶,使它们成为传送给StartOfThread的参数
把context结构的栈指针指向栈顶(第5步)指令指针指向startOfThread函数
MSDN中CreateThread原型: HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
参数说明:
lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL,表示使用缺省值。
dwStackSize:线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈的大小。
lpStartAddress,指向线程函数的指针,形式:@函数名,函数名称没有限制,但是必须以下列形式声明:DWORD WINAPI ThreadProc (PVOID pParam) ,格式不正确将无法调用成功。
lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为Nil。
dwCreationFlags :线程标志,可取值如下
CREATE_SUSPENDED: 创建一个挂起的线程
0 :创建后立即激活。
lpThreadId:保存新线程的id。
返回值:
函数成功,返回线程句柄;函数失败返回false。
函数说明:
创建一个线程。
语法:
hThread = CreateThread (&security_attributes, dwStackSize, ThreadProc,pParam, dwFlags, &idThread) ;
一般并不推荐使用 CreateTheard函数,而推荐使用RTL 库里的System单元中定义的 BeginTheard函数,因为这除了能创建一个线程和一个入口函数以外,还增加了几项保护措施。
CreateThread
微软在Windows API中提供了建立新的线程的函数CreateThread,
概述:
当使用CreateProcess调用时,系统将创建一个进程和一个主线程。CreateThread将在主线程的基础上创建一个新线程,大致做如下步骤:
1在内核对象中分配一个线程标识/句柄,可供管理,由CreateThread返回
2把线程退出码置为STILL_ACTIVE,把线程挂起计数置1
3分配context结构
4分配两页的物理存储以准备栈,保护页设置为PAGE_READWRITE,第2页设为PAGE_GUARD
5lpStartAddr和lpvThread值被放在栈顶,使它们成为传送给StartOfThread的参数
6把context结构的栈指针指向栈顶(第5步)指令指针指向startOfThread函数
MSDN中CreateThread原型:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
参数说明:
lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL,表示使用缺省值。
dwStackSize,线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈的大小。
lpStartAddress,指向线程函数的指针,形式:@函数名,函数名称没有限制,但是必须以下列形式声明:
DWORD WINAPI ThreadProc (PVOID pParam) ,格式不正确将无法调用成功。
lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为Nil。
dwCreationFlags :线程标志,可取值如下
CREATE_SUSPENDED: 创建一个挂起的线程
0 :创建后立即激活。
lpThreadId:保存新线程的id。
返回值:
函数成功,返回线程句柄;函数失败返回false。
函数说明:
创建一个线程。
语法:
hThread = CreateThread (&security_attributes, dwStackSize, ThreadProc,pParam, dwFlags, &idThread) ;
一般并不推荐使用 CreateTheard函数,而推荐使用RTL 库里的System单元中定义的 BeginTheard函数,因为这除了能创建一个线程和一个入口函数以外,还增加了几项保护措施。
C++多线程函数CreateThread如何使用?
#include
#include
using namespace std;
/*
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
*/
DWORD WINAPI Thread1Proc(LPVOID argv)
{
cout << "Thread1Func\n";
return 0;
}
int main()
{
HANDLE Thread;
DWORD ThreadID;
Thread1 = CreateThread(
0, //默认安全级别
0, //堆栈大小默认(2M)
ThreadProc, //线程入口函数
0, //参数没有
0, //创建时的状态
&Thread1ID //获得线程ID
);
cout << "main\n";
Sleep(100);
return 0;
}
HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, // 指向SECURITY_ATTRIBUTES 的指针,为新线程指定安全描述
__in SIZE_T dwStackSize, // 初始化线程堆栈尺寸
__in LPTHREAD_START_ROUTINE lpStartAddress, //线程函数所指向的地址 起始函数
__in_opt LPVOID lpParameter, // 给线程函数传递的参数
__in DWORD dwCreationFlags, // 有关线程的标志
__out_opt LPDWORD lpThreadId //系统分配给线程的ID
);
----第一个参数是安全属性,一般设为nil,使用缺省的安全属性。当我们想此线程有另外的子进程时,可改变它的属性。
----第二个参数是线程堆栈尺寸,一般设为0,表示与此应用的堆栈尺寸相同,即主线程与创建的线程一样长度的堆栈。并且其长度会根据需要自动变长。
----第三个参数,也是最重要的一个,是一个指向函数名的指针,但传递时很简单,只需在线程函数名前加上@就可以了。
----第四个参数是你需要向线程函数传递的参数,一般是一个指向结构的指针。不需传递参数时,则这个参数设为nil。
----第五个参数,传入与线程有关的一些标志,如果是CREATE_SUSPENDED,则创建一个挂起的线程,即这个线程本身已创建,它的堆栈也已创建。但这个线程不会被分配给CPU时间,只有当ResumeThread函数被调用后才能执行;当然,也可以调用SuspendThread函数再次挂起线程。要是标志为0,那么一旦建立线程,线程函数就被立即调用。一般传为0即可。
----第六个参数是系统分配给这个线程的唯一的ID标志
// Example.cpp
#include
#include
#include
using namespace std;
DWORD WINAPI StartThread(LPVOID iValue)
{
char lszParam[3];
strcpy(lszParam,(char *)iValue);
int iStart = atoi(lszParam);
for(int i=iStart;i<=iStart+10;i++)
cout<
<i<<endl;
return 0;
}
void main()
{
HANDLE hThread1,hThread2;
DWORD dwGenericThread;
char lszThreadParam[3];
strcpy(lszThreadParam,"3");
hThread1 = CreateThread(NULL,0,StartThread,&lszThreadParam,0,&dwGenericThread);
if(hThread1 == NULL)
{
DWORD dwError = GetLastError();
cout<<"Error in Creating thread"<
<dwerror<<endl ;
return;
}
WaitForSingleObject(hThread1,INFINITE);
//Second thread creation
strcpy(lszThreadParam,"30");
hThread2 = CreateThread(NULL,0,StartThread,&lszThreadParam,0,&dwGenericThread);
if(hThread1 == NULL)
{
DWORD dwError = GetLastError();
cout<<"Error in Creating thread"<
<dwerror<<endl ;
return;
}
WaitForSingleObject(hThread2,INFINITE);
}
</dwerror<
</dwerror<
</i<<endl;
WINAPI里的CreateThread函数
把这个函数声明为static 就可以了,主要是CreateThread()是在整个进程生存的,Run 声明为类的成员函数,类死了,这个函数就死了,他的生存范围小于了CreateThread(); 所以,RUN可以为全局函数,或者是声明为类的静态函数,就可以解决问题。。
传给CreateThread的函数,必须是全局函数或静态函数,不能使用类的普通函数
即,你可以使用如下函数声明:
static DWORD WINAPI Run(LPVOID LpParameter);
因为类的普通函数会传递类对象指针作为隐含参数,所以与CreateThread所要求的函数类型不匹配
CreateThread()函数每个参数都是什么意思,线程问题帮我都解释一下好么!
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
LPDWORD lpIDThread
);
lpsa:线程句柄的安全属性,比如子进程是否可以继承这个线程句柄,一般情况设置为NULL
cbStack:线程栈大小,一般取0表示默认大小
lpStartAddr:线程入口函数 typedef DWORD (__stdcall *LPTHREAD_START_ROUTINE) (
void* lpThreadParameter );在win32程序中默认的调用函数约定就是WINAPI ,__stdcall = WINAPI 。因此你可以声明你的入口函数为:
DWORD WINAPI ThreadProc( void* lpParamete) {//线程中你要做的事情}
lpvThreadParam:就是线程入口函数的参数,就是ThreadProc( void* lpParamete) 的参数
fdwCreate:控制线程创建的标志一般为0,表示线程立即启动。如果你想创建之后把线程挂起来可以传入CREATE_SUSPENDED ,传入这个参数你需要再适当的地方调用ResumeThread 启动线程
lpIDThread:是线程ID返回值,这个用来接收线程返回的ID
写了这么多我还是怕你不懂:
我举个例子吧,我不保证能运行成功,我也没去编译
DWORD WINAPI ThreadProc( void* lpParameter)
{
int *x = (int*)lpParameter;//获得参数的地址
MessageBox(NULL,TEXT("adf"),NULL,MB_OK);
}
DWORD dwThreadID;
int x = 0;
HANDLE hThread = CreateThread(0,0,ThreadProc,(void*)&x,0,&dwThreadID);
CloseHandle(hThread);
想学习好windows编程MSDN是必须了解的,你居然不知道什么是MSDN,MSDN就是帮助文档,你可以到百度搜一下并把它下载过来,这对你MFC、Windows API、C/C++等很有帮助的
createthread的线程如何等待线程结束
1. 线程函数返回
当线程函数返回时,该线程会被终止,始终应该采用该方式来结束线程的运行,因为这是确保所有线程资源被正确清除的唯一办法。如果线程按照该方式成功返回,则:
1)线程函数中创建的所有C++对象均能通过他们的析构函数正确的被撤销
2)操作系统将正确的释放线程运行栈所使用的内存
3)系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值
4)系统将该线程内核对象的使用计数递减
2.ExitThread函数
可以调用该函数,强制终止线程的运行。该函数将导致操作系统清除该线程所使用的所有操作系统资源。但是,C++资源(如类对象)将不被撤销。该方法通常是windows用来撤销线程的函数。因此,最好采用方法1来退出线程,而不是通过调用该函数来返回。
3.TerminateThread函数
调用该函数也能终止线程的运行,但与ExitThread函数不同,后者总是撤销调用的线程,而前者能够撤销任何线程。TerminateThread是异步运行的函数,也就是说,它告诉系统你想要线程终止运行,但是,该函数返回时,不能保证线程被撤销。如果需要确切地知道该线程已经终止运行,必须调用WaitForSingleObject或类似函数。当使用方法1和方法2撤销线程时,该线程的内存栈空间也被撤销。而如果使用TerminateThread,那么在拥有该线程的进程终止运行之前,系统不撤销该线程的运行栈。
4.进程终止运行时终止线程
在进程终止运行时,该进程中的所有线程全部终止运行,由于整个进程已经被关闭,进程所使用的所有资源肯定已被清除。这当然包括所有线程的栈空间。使用ExitProcess和TerminateProcess函数,会导致进程中的剩余线程被强制撤销,就像从每个剩余的线程调用TerminataProcess一样,因此,这也意味着正确的应用程序清除没有发生,即C++对象析构函数没被调用,数据没有转移至磁盘等等。
请教CreateThread使用本类的成员函数问题
一般这样调就可以了:
CreateThread(NULL,0,ThreadProc,NULL,0,NULL)
第三个参数就是新线程的函数名,如果需要给新线程函数传递值的话就在第四个参数传。
新线程回调函数是这样的:
DWORD WINAPI ThreadProc(PVOID pParam)
{
return 0;
}
创建线程与常用的函数调用有什么区别
CreateThread是Windows的API函数(SDK函数的标准形式,直截了当的创建方式,任何场合都可以使用),提供操作系统级别的创建线程的操作,且仅限于工作者线程。不调用MFC和RTL的函数时,可以用CreateThread,其它情况不要轻易。在使用的过程中要考虑到进程的同步与互斥的关系(防止死锁)。线程函数定义为:DWORD WINAPI _yourThreadFun(LPVOID pParameter)。
如何避免使用CreateThread函数导致的内存泄露
CreateThread导致内存泄露的原因
这得从C运行时库说起了。
VC运行时库,有一个宏errno,用来获得上一步操作的错误码,类似于Win32中的GetLastError()函数。在多线程环境下,不同线程调用errno返回的都是caller线程的错误码,绝对不会混淆,这是因为使用了TLS技术。
TLS,Thread Local Storage,是用来存取线程相关数据的一种技术,在Win32中由操作系统的Tls*系列函数提供支持。例如,可以在程序开始的地方调用TlsAlloc()函数,获得一个TLS index,这个index在进程范围内有效,然后可以创建n个线程,在每个线程中使用TlsSetValue(index,data)将线程相关数据和index关联起来,使用TlsGetValue(index)来获取当前线程和index相关联的的线程相关数据。
查看msdn可以发现,Tls*函数的定义如下:
[cpp] view plaincopy
DWORD WINAPI TlsAlloc(void);
BOOL WINAPI TlsSetValue(
__in DWORD dwTlsIndex,
__in LPVOID lpTlsValue
);
LPVOID WINAPI TlsGetValue(
__in DWORD dwTlsIndex
);
BOOL WINAPI TlsFree(
__in DWORD dwTlsIndex
);
观察TlsSetValue/TlsGetValue的原型可以发现,与index关联的数据只能是void *类型,因此通常的做法是在线程开始的时候,为这个线程分配一块内存,用于存储所有与线程相关的数据,然后把这块内存的起始地址与index关联起来。如果这块内存在线程退出的时候没有释放掉,那就有内存泄露的危险。
回到errno,来看看C运行时库是如何实现errno的。
errno的声明和实现如下:
[c-sharp] view plaincopy
/* error.h - errno的声明 */
_CRTIMP extern int * __cdecl _errno(void);
#define errno (*_errno())
/* dosmap.c - errno的实现 */
int * __cdecl _errno(
void
)
{
_ptiddata ptd = _getptd_noexit();
if (!ptd) {
return &ErrnoNoMem;
} else {
return ( &ptd->_terrno );
}
}
观察_errno的代码,函数首先调用了_getptd_noexit()函数,这个函数的代码如下:
[cpp] view plaincopy
/* tiddata.c - _getptd_noexit()实现 */
_ptiddata __cdecl _getptd_noexit (
void
)
{
_ptiddata ptd;
DWORD TL_LastError;
TL_LastError = GetLastError();
#ifdef _M_IX86
/*
* Initialize FlsGetValue function pointer in TLS by calling __set_flsgetvalue()
*/
if ( (ptd = (__set_flsgetvalue())(__flsindex)) == NULL ) {
#else /* _M_IX86 */
if ( (ptd = FLS_GETVALUE(__flsindex)) == NULL ) {
#endif /* _M_IX86 */
/*
* no per-thread data structure for this thread. try to create
* one.
*/
#ifdef _DEBUG
extern void * __cdecl _calloc_dbg_impl(size_t, size_t, int, const char *, int, int *);
if ((ptd = _calloc_dbg_impl(1, sizeof(struct _tiddata), _CRT_BLOCK, __FILE__, __LINE__, NULL)) != NULL) {
#else /* _DEBUG */
if ((ptd = _calloc_crt(1, sizeof(struct _tiddata))) != NULL) {
#endif /* _DEBUG */
if (FLS_SETVALUE(__flsindex, (LPVOID)ptd) ) {
/*
* Initialize of per-thread data
*/
_initptd(ptd,NULL);
ptd->_tid = GetCurrentThreadId();
ptd->_thandle = (uintptr_t)(-1);
}
else {
/*
* Return NULL to indicate failure
*/
_free_crt(ptd);
ptd = NULL;
}
}
}
SetLastError(TL_LastError);
return(ptd);
}
_getptd_noexit()函数首先通过TLS查找线程相关数据,如果没有找到,就分配一块内存,存放_tiddata结构,并将这块内存与__flsindex相关联。由此可见,errno的确使用了TLS技术,而且通过查找_getptd_noexit() 可以发现,VC运行时库中很多很多函数都使用了TLS,errno只不过是其中的一个典型。