线程

   界面线程与工作者线程

       二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。      

       工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等。

       用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。

       但对于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编辑  收藏  举报

导航