线程
界面线程与工作者线程
二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。
工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等。
用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。
但对于Win32的API编程而言,这两种线程是没有区别的,它们都只需线程的启动地址即可启动线程来执行任务
CreateThread是由操作系统提供的接口,而AfxBeginThread和_BeginThread则是编译器对它的封装。
用_beginthreadex()、_endthreadex函数应该是最佳选择,且都是C Run-time Library中的函数,函数的参数和数据类型都是C Run-time Library中的类型,这样在启动线程时就不需要进行Windows数据类型和C Run-time Library中的数据类型之间的转化,从而,减低了线程启动时的资源消耗和时间的消耗。但使用_beginthread,无法创建带有安全属性的新线程,无法创建暂停的线程,也无法获得 线程ID,_endthread的情况类似,它不带参数,这意味这线程的退出代码必须硬编码为0。
CreateThread
Declared in Winbase.h; include Windows.h.
提供操作系统级别的创建线程的操作,且仅限于工作者线程。不调用MFC和RTL的函数时,可以用CreateThread,其它情况不要轻易。在使用的过程中要考虑到进程的同步与互斥的关系(防止死锁)。
HANDLE CreateThread(
__in SEC_ATTRS SecurityAttributes,
__in ULONG StackSize,
__in SEC_THREAD_START StartFunction,
__in PVOID ThreadParameter,
__in ULONG CreationFlags,
__out PULONG ThreadId
);
DWORD WINAPI ThreadProc( [in] LPVOID lpParameter );
第一个参数是指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL。
第二个参数是用于新线程的初始堆栈大小,默认值为0。在任何情况下,Windows根据需要动态延长堆栈的大小。
第三个参数是指向线程函数的指标。函数名称没有限制,但是必须以下列形式声明:
DWORD WINAPI ThreadProc (PVOID pParam) ;
第四个参数为传递给ThreadProc的参数。这样主线程和从属线程就可以共享数据。
第五个参数通常为0,但当建立的线程不马上执行时为旗标CREATE_SUSPENDED。线程将暂停直到呼叫ResumeThread来恢复线程的执行为止。
第六个参数是一个指标,指向接受执行绪ID值的变量。
使用CreateProcess调用时,系统将创建一个进程和一个主线程。CreateThread将在主线程的基础上创建一个新线程,大致做如下步骤:
1 在内核对象中分配一个线程标识/句柄,可供管理,由CreateThread返回
2 把线程退出码置为STILL_ACTIVE,把线程挂起计数置1
3 分配context结构
4 分配两页的物理存储以准备栈,保护页设置为PAGE_READWRITE,第2页设为PAGE_GUARD
5 lpStartAddr和lpvThread值被放在栈顶,使它们成为传送给StartOfThread的参数
6 把context结构的栈指针指向栈顶,指令指针指向startOfThread函数
_beginthread
process.h
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 );
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 is either __stdcall or __clrcall.
//第1个参数:安全属性,NULL为默认安全属性
//第2个参数:指定线程堆栈的大小。如果为0,则线程堆栈大小和创建它的线程的相同。一般用0
//第3个参数:指定线程函数的地址,也就是线程调用执行的函数地址(用函数名称即可,函数名称就表示地址)
//第4个参数:传递给线程的参数的指针,可以通过传入对象的指针,在线程函数中再转化为对应类的指针
//第5个参数:线程初始状态,0:立即运行;CREATE_SUSPEND:suspended(悬挂)
//第6个参数:用于记录线程ID的地址
AfxBeginThread
CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
UINT __cdecl AfxThreadProc( LPVOID pParam );
#include <process.h> // for _beginthread() DWORD g_dwCount = 0; BOOL g_bLoop = TRUE; CRITICAL_SECTION g_cs; HANDLE g_hCreateThread = NULL; DWORD WINAPI CreateThreadProc( LPVOID lpParameter ); HANDLE g_hbeginthread = NULL; unsigned __stdcall _beginthreadProc(void* pParameter); HANDLE g_hAfxthread = NULL; UINT AfxBeginThreadProc(LPVOID pParam); int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { InitializeCriticalSection(&g_cs); g_hCreateThread = ::CreateThread( NULL, 0, CreateThreadProc, 0, 0, NULL ); unsigned uTID1 = 0; g_hbeginthread = (HANDLE)_beginthreadex( NULL/* security */, 0/* stack size */, _beginthreadProc, NULL, 0, &uTID1 ); CWinThread* pAfx1 = AfxBeginThread(AfxBeginThreadProc, NULL); g_hAfxthread = pAfx1->m_hThread; Sleep(1234); g_bLoop = FALSE; WaitForSingleObject(g_hCreateThread, INFINITE); CloseHandle(g_hCreateThread); g_hCreateThread = NULL; WaitForSingleObject(g_hbeginthread, INFINITE); CloseHandle(g_hbeginthread); g_hbeginthread = NULL; WaitForSingleObject(g_hAfxthread, INFINITE); CloseHandle(g_hAfxthread); g_hAfxthread = NULL; return 0; } DWORD WINAPI CreateThreadProc( LPVOID lpParameter ) { while (g_bLoop) { EnterCriticalSection(&g_cs); g_dwCount++; printf("CreateThreadProc : %d\r\n", g_dwCount); LeaveCriticalSection(&g_cs); } return 0; } unsigned __stdcall _beginthreadProc(void * pParameter) { while (g_bLoop) { EnterCriticalSection(&g_cs); g_dwCount++; printf("_beginthreadProc : %d\r\n", g_dwCount); LeaveCriticalSection(&g_cs); } return 0; } UINT AfxBeginThreadProc( LPVOID pParam ) { while (g_bLoop) { EnterCriticalSection(&g_cs); g_dwCount++; printf("AfxBeginThreadProc : %d\r\n", g_dwCount); LeaveCriticalSection(&g_cs); } return 0; }
posted on 2016-11-02 16:43 NoneButNow 阅读(229) 评论(0) 编辑 收藏 举报