R3多线程
方法1:
ULONG WINAPI ThreadProc(void* arg)
{
return 1;
}
VOID StartThread()
{
HANDLE hThread = NULL;
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
hThread = NULL;
}
方法2:
UINT WINAPI ThreadProc(LPVOID lpParameter)
{
return 0;
}
unsigned tid = 0;
HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0, ThreadProc, NULL, 0, &tid);
WaitForSingleObject( hThread, INFINITE );
CloseHandle(hThread);
hThread = NULL;
方法3:
UINT threadProc(LPVOID v)
{
AfxEndThread(0);
}
CWinThread *pThreadR = AfxBeginThread(threadProc,(LPVOID)param);
pThreadR->SuspendThread();
pThreadR->m_bAutoDelete = FALSE;
pThreadR->ResumeThread();
if (WaitForSingleObject(pThreadR->m_hThread, 2*1000)==WAIT_TIMEOUT)
{
TerminateThread(pThreadR->m_hThread, 0);
}
delete (pThreadR);
pThreadR = NULL;
三个函数的区别:
CreateThread:是Windows的API函数(SDK函数的标准形式,直截了当的创建方式,任何场合都可以使用),提供操作系统级别的创建线程的操作,且仅限于工作者线程。不调用MFC和RTL的函数时,可以用CreateThread,其它情况不要使用。因为:
C Runtime中需要对多线程进行纪录和初始化,以保证C函数库工作正常。
MFC也需要知道新线程的创建,也需要做一些初始化工作。
有些CRT的函数象malloc(),fopen(),_open(),strtok(),ctime(),或localtime()等函数需要专门的线程局部存储的数据块,这个数据块通常需要在创建线程的时候就建立,如果使用CreateThread,这个数据块就没有建立,但函数会自己建立一个,然后将其与线程联系在一起,这意味着如果你用CreateThread来创建线程,然后使用这样的函数,会有一块内存在不知不觉中创建,而且这些函数并不将其删除,而CreateThread和ExitThread也无法知道这件事,于是就会有Memory Leak,在线程频繁启动的软件中,迟早会让系统的内存资源耗尽。
_beginthreadex:MS对C Runtime库的扩展SDK函数,首先针对C Runtime库做了一些初始化的工作,以保证C Runtime库工作正常。然后,调用CreateThread真正创建线程。
AfxBeginThread:MFC中线程创建的MFC函数,首先创建了相应的CWinThread对象,然后调用CWinThread::CreateThread,在CWinThread::CreateThread中,完成了对线程对象的初始化工作,然后,调用_beginthreadex(AfxBeginThread相比较更为安全)创建线程。它让线程能够响应消息,可用于界面线程,也可以用于工作者线程。
三个函数的应用条件:
AfxBeginThread:在MFC中用,工作者线程/界面线程
_beginthreadex: 调用了C运行库的,应该用这个,但不能用在MFC中。
CreateThread:工作者线程,MFC中不能用,C Runtime中不能用。所以任何时候最好都不要用。
AfxBeginThread_beginthreadexCreateThread
内核多线程创建:
VOID DoFind(IN PVOID pContext)
{
}
void StartThread()
{
HANDLE hThread = NULL;
PVOID objtowait = 0;
NTSTATUS dwStatus =
PsCreateSystemThread(
&hThread,
0,
NULL,
(HANDLE)0,
NULL,
DoFind,
NULL
);
if (!NT_SUCCESS(dwStatus)
{
return;
}
if ((KeGetCurrentIrql())!=PASSIVE_LEVEL)
{
dwStatus=KfRaiseIrql(PASSIVE_LEVEL);
}
if ((KeGetCurrentIrql())!=PASSIVE_LEVEL)
{
return;
}
ObReferenceObjectByHandle(
hThread,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
&objtowait,
NULL
);
KeWaitForSingleObject(objtowait,Executive,KernelMode,FALSE,NULL);
ObDereference(&objtowait);
return;
}