精华内容
下载资源
问答
  • MFC 获取线程ID

    千次阅读 2014-05-15 15:10:07
    于是网上找各种获取线程ID的方法,把找到的几种写下来方便以后用   1.通过进程映射名称获取主线程ID(进程映射名应为全大写,如谷歌浏览器的进程名:CHROME.EXE)   DWORD WINAPI GetThreadIDByName...

    翻回以前写的HOOK 程序,发现之前的挂钩线程ID部分有问题。。于是网上找各种获取线程ID的方法,把找到的几种写下来方便以后用

     

    1.通过进程映射名称获取主线程ID(进程映射名应为全大写,如谷歌浏览器的进程名:CHROME.EXE)

     

    DWORD WINAPI GetThreadIDByName(LPCTSTR lpFilename)
    {
    	DWORD dwThreadID = 0;
    	PROCESSENTRY32 pe32;
    	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    	if(hProcessSnap == INVALID_HANDLE_VALUE) 
    		return 0;
    	if(!Process32First(hProcessSnap,&pe32))
    	{
    		do
    		{
    			_strupr(pe32.szExeFile);
    			if(!strcmp(pe32.szExeFile,lpFilename))
    			{
    				//遍历线程查找对应ID
    				HANDLE hThreadSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
    				THREADENTRY32 te32 = {sizeof(te32)};
    				if(::Thread32First(hThreadSnap,&te32))
    				{
    					do
    					{
    						if(te32.th32OwnerProcessID == pe32.th32ProcessID)
    						{
    							dwThreadID = te32.th32ThreadID;
    							break;
    						}
    					}
    					while(::Thread32Next(hThreadSnap,&te32));
    				}
    				CloseHandle(hThreadSnap);
    				break;
    			}
    		}
    		while(Process32Next(hProcessSnap,&pe32));
    	}
    	CloseHandle(hProcessSnap);
    	return dwThreadID;
    }

     

     

    2.GetWindowThreadProcessId.这个函数用于获取创建某窗口的线程,进程ID

    DWORD GetWindowThreadProcessId(HWND hWnd, LPDWORD lpdwProcessId);

    hWnd 是目标窗口的句柄

    lpdwProcessId 是用来存放进程ID的地址

     

    3.GetCurrentThreadId.获取当前线程ID

    返回值就是线程ID

     

    4.GetThreadId.根据线程句柄获取线程ID

    DWORD WINAPI GetThreadId(HANDLE hThread);

    hThread 就是线程句柄

    返回值就是线程ID

     

     

    暂时只找到这么多,以后找到再补上

     

    展开全文
  • MFC 获取当前线程ID的问题

    千次阅读 2013-12-02 14:36:12
    CString str;  DWORD id = ::GetCurrentThreadId...//获取最近线程ID  str.Format(_T("ThreadID = %ld, %ud, %ud, %ld\r\n"), id, uMsg, idEvent, dwTime);  OutputDebugString(_T("+++++") + str + _T("\r\n"));
    CString str;
     DWORD id =::GetCurrentThreadId();//获取最近线程的ID
     str.Format(_T("ThreadID = %ld, %ud, %ud,%ld\r\n"), id, uMsg, idEvent, dwTime);
     OutputDebugString(_T("+++++") + str + _T("\r\n"));
    展开全文
  • ProcessID.Format("%d",info->th32ProcessID); strProcessName.Format("%s",info->szExeFile); while(Process32Next(handle,info)!=FALSE) { ProcessID.Format("%5d",info->th32ProcessID); ...
    //
    
    bool CStudentComputerControl::FindProcess(CString ProcessName)
    {
        HANDLE handle=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    PROCESSENTRY32* info=new PROCESSENTRY32;
    info->dwSize=sizeof(PROCESSENTRY32);
    bool result=false;
    if(Process32First(handle,info))
    {
    if(GetLastError()==ERROR_NO_MORE_FILES )
    {
    AfxMessageBox("No More Process");
    result=false;
    }
    else
    {
    CString ProcessID,strProcessName;
    ProcessID.Format("%d",info->th32ProcessID);
    strProcessName.Format("%s",info->szExeFile);
    while(Process32Next(handle,info)!=FALSE)
    {
    ProcessID.Format("%5d",info->th32ProcessID);
    strProcessName.Format("%s",info->szExeFile);
    if (!strProcessName.Compare(ProcessName))
    {
    result=true;
    break;
    }
    }
    }
    }
    CloseHandle(handle);
    return result;

    }
    展开全文
  • MFC线程的创建

    千次阅读 2016-06-16 08:57:21
    MFC线程简介MFC线程基础线程函数工作线程的创建用户界面线程的创建 1用户界面线程实例12用户界面线程实例2 MFC线程的创建 1.MFC线程简介 MFC对多线程进行了一层简单的封装,在Visual C++中每...
    目录(?) 
    
    1. MFC多线程的创建
      1. MFC多线程简介
      2. MFC多线程基础
      3. 线程函数
      4. 工作线程的创建
      5. 用户界面线程的创建
        1. 1用户界面线程实例1
        2. 2用户界面线程实例2

    MFC多线程的创建

    1.MFC多线程简介

    MFC对多线程进行了一层简单的封装,Visual C++中每个线程都是从CWinThread类继承而来的。每一个应用程序的执行都有一个主线程,这个主线程也是从CWinThread类继承而来的。可以利用CWinThread对象创建应用程序执行的其它线程。

    MFC用CWinThread对象来表示所有线程。利用MFC可以创建两种线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等。用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。但对于Win32API编程而言,这两种线程是没有区别的,它们都只需线程的启动地址即可启动线程来执行任务。

    2.MFC多线程基础

    为了深入了解MFC下创建线程的方法,我们先深入学习一下CWinThread类。CWinThread类在MFC类结构中的位置如下图所示:

    图1:CWinThread类在mfc类结构中的位置

    详细的MFC类结构图请参考MSDN: http://msdn.microsoft.com/zh-cn/library/ws8s10w4(VS.90).aspx

    首先看一下类CWinThread的声明。类CWinThread的声明在afxwin.h中:

    /

    Class CWinThread :publicCCmdTarget

    {

        DECLARE_DYNAMIC(CWinThread)

    public:

    //构造函数

        CWinThread();

    //用来具体创建线程的函数

        BOOL CreateThread(DWORDdwCreateFlags = 0,UINTnStackSize = 0,

           LPSECURITY_ATTRIBUTES lpSecurityAttrs= NULL);

    // Attributes

    //主窗口,(通常使用AfxGetApp()->m_pMainWnd可以得到)

        CWnd* m_pMainWnd;       // main window(usually same AfxGetApp()->m_pMainWnd)

    //活动窗口,可能不是主窗口

        CWnd* m_pActiveWnd;     // active mainwindow (may not be m_pMainWnd)

        BOOL m_bAutoDelete;     // enables'delete this' after thread termination

        // only valid while running

    //该线程的句柄

        HANDLE m_hThread;       // thisthread's HANDLE

        operator HANDLE() const;

    //该线程的ID

        DWORD m_nThreadID;      // thisthread's ID

    //线程优先级

        int GetThreadPriority();

        BOOL SetThreadPriority(int nPriority);

    // Operations

    //挂起线程

        DWORD SuspendThread();

    //启动线程

        DWORD ResumeThread();

    //发送线程消息

        BOOL PostThreadMessage(UINT message, WPARAM wParam, LPARAM lParam);

    // Overridables

        // 线程初始化,每个应用程序都可以重载该函数

        virtual BOOL InitInstance();

        // running and idle processing

        virtual int Run();

        virtual BOOL PreTranslateMessage(MSG*pMsg);

        virtual BOOL PumpMessage();    // low level message pump

        virtual BOOL OnIdle(LONGlCount);// return TRUEif more idle processing

        virtual BOOL IsIdleMessage(MSG*pMsg); // checks for special messages

        // thread termination

        virtual int ExitInstance(); //default will 'delete this'

        // Advanced: exception handling

        virtual LRESULT ProcessWndProcException(CException*e,constMSG*pMsg);

        // Advanced: handling messages sent to message filter hook

        virtual BOOL ProcessMessageFilter(intcode,LPMSGlpMsg);

        // Advanced: virtual access to m_pMainWnd

        virtual CWnd* GetMainWnd();

    // Implementation

    public:

        virtual ~CWinThread();

    #ifdef _DEBUG

        virtual void AssertValid() const;

        virtual void Dump(CDumpContext&dc)const;

    #endif

        void CommonConstruct();

        virtual void Delete();

           // 'delete this' only if m_bAutoDelete == TRUE

    public:

        // constructor used by implementation of AfxBeginThread

        CWinThread(AFX_THREADPROCpfnThreadProc,LPVOIDpParam);

        // valid after construction

        LPVOID m_pThreadParams;// generic parameters passed to starting function

        AFX_THREADPROC m_pfnThreadProc;

        // set after OLE is initialized

        void (AFXAPI*m_lpfnOleTermOrFreeLib)(BOOL,BOOL);

        COleMessageFilter* m_pMessageFilter;

    protected:

        BOOL DispatchThreadMessageEx(MSG* msg);  // helper

        void DispatchThreadMessage(MSG* msg);  // obsolete

    };

    /

    有些函数是不是很眼熟呀,在前面的文章中已经介绍和使用过啦。MFC类就是这样的,它无非就是简单封装一些API函数,并添加一些自己的函数而构成的。不用MFC我们照样可以编写很优秀的程序,MFC的宗旨就是简化程序设计,让你可以很容易入门和简单的使用,也催生了大量的程序员。但对喜欢刨根问底的朋友却是一道很厚的墙

    下面几个函数是多线程编程中经常用到的几个全局函数:

    //创建工作线程

    CWinThread* AFXAPIAfxBeginThread(

    AFX_THREADPROC pfnThreadProc,//线程函数

     LPVOID pParam,//传给线程函数的参数

    int nPriority =THREAD_PRIORITY_NORMAL,//线程的优先级

    UINT nStackSize = 0,//堆栈大小

    DWORD dwCreateFlags = 0,//创建起始状态标志

       LPSECURITY_ATTRIBUTES lpSecurityAttrs= NULL//线程的安全属性

    );

    //创建用户界面线程

    CWinThread* AFXAPIAfxBeginThread(

    CRuntimeClass* pThreadClass,//从CWinThread派生的类的RUNTIME_CLASS

    int nPriority =THREAD_PRIORITY_NORMAL,//线程的优先级

       UINT nStackSize = 0,// 堆栈大小

    DWORD dwCreateFlags = 0,// 创建起始状态标志

     LPSECURITY_ATTRIBUTESlpSecurityAttrs =NULL//线程的安全属性

    );

    //获取线程对象

    CWinThread* AFXAPIAfxGetThread();

    //获取当前消息

    MSG* AFXAPIAfxGetCurrentMessage();

    //结束线程执行

    void AFXAPIAfxEndThread(UINTnExitCode,BOOLbDelete =TRUE);

    //初始化线程

    void AFXAPIAfxInitThread();

    //终止线程执行

    void AFXAPIAfxTermThread(HINSTANCEhInstTerm =NULL);

    仔细阅读以上类的说明能学到不少东西:

    (1)   CWinThead类通过CreateThread()成员函数来创建线程,这个函数的声明和Win32APICreateThread()的参数相似

    (2)每个函数在运行后都有一个句柄和ID号。

    (3)通过设置属性m_bAutoDelete,可决定线程在运行结束后线程对象是否自动删除,它的访问权限是public型的,可以直接进行设置。一般情况下,线程对象的生命周期和线程的生命周期一致。如果你想改变线程对象的生命周期,可设置该属性为FALSE。

    (4)MFC下的多线程仍然支持线程的挂起和启动。

    (5)具有PreTranslateMessage()、PumpMessage()等函数,供用户界面线程的消息机制使用。

    在MFC中实际上是调用AfxBeginThread()函数来创建线程的。那么为什么不直接使用::CreateThread()_beginthread()函数来创建线程呢?只要看一下CWinThread类的实现中的相关代码就明白了。在thrdcore.cpp文件中的相关代码如下:

    ==========================================================================================================

    CWinThread* AFXAPI AfxGetThread()

    {

        // check for current thread in module thread state

        AFX_MODULE_THREAD_STATE* pState= AfxGetModuleThreadState();

        CWinThread* pThread= pState->m_pCurrentWinThread;

        return pThread;

    }


    MSG* AFXAPI AfxGetCurrentMessage()

    {

      _AFX_THREAD_STATE* pState= AfxGetThreadState();

      ASSERT(pState);

      return &(pState->m_msgCur);

    }


    CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,int nPriority,UINT nStackSize, DWORD dwCreateFlags,

        LPSECURITY_ATTRIBUTESlpSecurityAttrs)

    {

    #ifndef _MT

        pfnThreadProc;

        pParam;

        nPriority;

        nStackSize;

        dwCreateFlags;

        lpSecurityAttrs;

        return NULL;

    #else

        ASSERT(pfnThreadProc!=NULL);

        CWinThread* pThread=DEBUG_NEWCWinThread(pfnThreadProc,pParam);

        ASSERT_VALID(pThread);

        if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED,nStackSize,

           lpSecurityAttrs))

        {

           pThread->Delete();

           return NULL;

        }

        VERIFY(pThread->SetThreadPriority(nPriority));

        if (!(dwCreateFlags&CREATE_SUSPENDED))

           VERIFY(pThread->ResumeThread() != (DWORD)-1);

        return pThread;

    #endif //!_MT)

    }


    CWinThread* AFXAPI AfxBeginThread(CRuntimeClass*pThreadClass,

        int nPriority, UINT nStackSize,DWORD dwCreateFlags,

        LPSECURITY_ATTRIBUTES lpSecurityAttrs)

    {

    #ifndef _MT

        pThreadClass;

        nPriority;

        nStackSize;

        dwCreateFlags;

        lpSecurityAttrs;

        return NULL;

    #else

        ASSERT(pThreadClass!=NULL);

        ASSERT(pThreadClass->IsDerivedFrom(RUNTIME_CLASS(CWinThread)));

        CWinThread* pThread= (CWinThread*)pThreadClass->CreateObject();

        if (pThread ==NULL)

           AfxThrowMemoryException();

        ASSERT_VALID(pThread);

        pThread->m_pThreadParams=NULL;

        if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED,nStackSize,

           lpSecurityAttrs))

        {

           pThread->Delete();

           return NULL;

        }

        VERIFY(pThread->SetThreadPriority(nPriority));

        if (!(dwCreateFlags&CREATE_SUSPENDED))

        {

           ENSURE(pThread->ResumeThread() != (DWORD)-1);

        }

        return pThread;

    #endif //!_MT

    }

     

    void AFXAPI AfxEndThread(UINTnExitCode,BOOLbDelete)

    {

    #ifndef _MT

        nExitCode;

        bDelete;

    #else

        // remove current CWinThread object from memory

        AFX_MODULE_THREAD_STATE* pState= AfxGetModuleThreadState();

        CWinThread* pThread= pState->m_pCurrentWinThread;

        if (pThread !=NULL)

        {

           ASSERT_VALID(pThread);

           ASSERT(pThread!=AfxGetApp());

           // cleanup OLE if required

           if (pThread->m_lpfnOleTermOrFreeLib !=NULL)

               (*pThread->m_lpfnOleTermOrFreeLib)(TRUE,FALSE);

           if (bDelete)

               pThread->Delete();

           pState->m_pCurrentWinThread=NULL;

        }

        // allow cleanup of any thread local objects

        AfxTermThread();

        // allow C-runtime to cleanup, and exit the thread

        _endthreadex(nExitCode);

    #endif //!_MT

    }

    /

    // Global functions forthread initialization and thread cleanup

     

    LRESULT CALLBACK _AfxMsgFilterHook(intcode,WPARAMwParam,LPARAMlParam);

     

    void AFXAPI AfxInitThread()

    {

        if (!afxContextIsDLL)

        {

           // set message filter proc

           _AFX_THREAD_STATE* pThreadState= AfxGetThreadState();

           ASSERT(pThreadState->m_hHookOldMsgFilter ==NULL);

           pThreadState->m_hHookOldMsgFilter= ::SetWindowsHookEx(WH_MSGFILTER,

               _AfxMsgFilterHook, NULL,::GetCurrentThreadId());

        }

    }

     

    extern CThreadSlotData* _afxThreadData;

    void AFXAPI AfxTermThread(HINSTANCEhInstTerm)

    {

        try

        {

    #ifdef _DEBUG

           // check for missing AfxLockTempMap calls

           if (AfxGetModuleThreadState()->m_nTempMapLock != 0)

           {

               TRACE(traceAppMsg,0,"Warning: Temp map lock count non-zero(%ld).\n",

                  AfxGetModuleThreadState()->m_nTempMapLock);

           }

    #endif

           AfxLockTempMaps();

           AfxUnlockTempMaps(-1);

        }

        catch( CException*e )

        {

           e->Delete();

        }

        try

        {

           // cleanup thread local tooltip window

           if (hInstTerm ==NULL)

           {

               AFX_MODULE_THREAD_STATE*pModuleThreadState=AfxGetModuleThreadState();

               if ((pModuleThreadState!=NULL) &&

                  (pModuleThreadState->m_pToolTip!=NULL))

               {

                  pModuleThreadState->m_pToolTip->DestroyWindow();

                  delete pModuleThreadState->m_pToolTip;

                  pModuleThreadState->m_pToolTip=NULL;

               }

           }

        }

        catch( CException*e )

        {

           e->Delete();

        }

        try

        {

           // cleanup the rest of the thread local data

           if (_afxThreadData!=NULL)

               _afxThreadData->DeleteValues(hInstTerm,FALSE);

        }

        catch( CException*e )

        {

           e->Delete();

        }

    }

    /

    // CWinThread construction

     

    CWinThread::CWinThread(AFX_THREADPROCpfnThreadProc,LPVOIDpParam)

    {

        m_pfnThreadProc = pfnThreadProc;

        m_pThreadParams = pParam;

        CommonConstruct();

    }

     

    CWinThread::CWinThread()

    {

        m_pThreadParams = NULL;

        m_pfnThreadProc = NULL;

        CommonConstruct();

    }

     

    void CWinThread::CommonConstruct()

    {

        m_pMainWnd = NULL;

        m_pActiveWnd = NULL;

        // no HTHREAD until it is created

        m_hThread = NULL;

        m_nThreadID = 0;

        _AFX_THREAD_STATE* pState= AfxGetThreadState();

        // initialize message pump

    #ifdef _DEBUG

        pState->m_nDisablePumpCount= 0;

    #endif

        pState->m_msgCur.message =WM_NULL;

        pState->m_nMsgLast=WM_NULL;

        ::GetCursorPos(&(pState->m_ptCursorLast));

        // most threads are deleted when not needed

        m_bAutoDelete = TRUE;

        // initialize OLE state

        m_pMessageFilter = NULL;

        m_lpfnOleTermOrFreeLib = NULL;

    }

     

    CWinThread::~CWinThread()

    {

        // free thread object

        if (m_hThread !=NULL)

           CloseHandle(m_hThread);

        // cleanup module state

        AFX_MODULE_THREAD_STATE* pState= AfxGetModuleThreadState();

        if (pState->m_pCurrentWinThread ==this)

           pState->m_pCurrentWinThread=NULL;

    }

     

    BOOL CWinThread::CreateThread(DWORDdwCreateFlags,UINTnStackSize,

        LPSECURITY_ATTRIBUTES lpSecurityAttrs)

    {

    #ifndef _MT

        dwCreateFlags;

        nStackSize;

        lpSecurityAttrs;

        return FALSE;

    #else

        ENSURE(m_hThread==NULL); // already created?

        // setup startup structure for thread initialization

        _AFX_THREAD_STARTUP startup;memset(&startup,0,sizeof(startup));

        startup.pThreadState=AfxGetThreadState();

        startup.pThread=this;

        startup.hEvent= ::CreateEvent(NULL,TRUE,FALSE,NULL);

        startup.hEvent2= ::CreateEvent(NULL,TRUE,FALSE,NULL);

        startup.dwCreateFlags=dwCreateFlags;

        if (startup.hEvent ==NULL||startup.hEvent2==NULL)

        {

           TRACE(traceAppMsg,0,"Warning: CreateEvent failed inCWinThread::CreateThread.\n");

           if (startup.hEvent !=NULL)

               ::CloseHandle(startup.hEvent);

           if (startup.hEvent2 !=NULL)

               ::CloseHandle(startup.hEvent2);

           return FALSE;

        }

     

        // create the thread (it may or may not start to run)

        m_hThread = (HANDLE)(ULONG_PTR)_beginthreadex(lpSecurityAttrs,nStackSize

           &_AfxThreadEntry, &startup,dwCreateFlags |CREATE_SUSPENDED,(UINT*)&m_nThreadID);

        if (m_hThread ==NULL)

        {

           ::CloseHandle(startup.hEvent);

           ::CloseHandle(startup.hEvent2);

           return FALSE;

        }

     

        // start the thread just for MFC initialization

        VERIFY(ResumeThread()!= (DWORD)-1);

        VERIFY(::WaitForSingleObject(startup.hEvent,INFINITE) ==WAIT_OBJECT_0);

        ::CloseHandle(startup.hEvent);

        // if created suspended, suspend it until resume threadwakes it up

        if (dwCreateFlags&CREATE_SUSPENDED)

           VERIFY(::SuspendThread(m_hThread) != (DWORD)-1);

        // if error during startup, shut things down

        if (startup.bError)

        {

           VERIFY(::WaitForSingleObject(m_hThread,INFINITE)==WAIT_OBJECT_0);

           ::CloseHandle(m_hThread);

           m_hThread = NULL;

           ::CloseHandle(startup.hEvent2);

           return FALSE;

        }

     

        // allow thread to continue, once resumed (it may alreadybe resumed)

        VERIFY(::SetEvent(startup.hEvent2));

        return TRUE;

    #endif //!_MT

    }

     

    void CWinThread::Delete()

    {

        // delete thread if it is auto-deleting

        if (m_bAutoDelete)

           delete this;

    }

    /

    在创建一个新的线程时,不必直接创建线程对象,因为线程对象是由全局函数AxCreateThread()自动产生的。只要首先定义一个CWinThread类指针,然后调用全局函数AxCreateThread()来产生一个新的线程对象,并调用线程类的CreateThread()成员函数来具体创建线程,最后将新的线程对象的指针返回。应该将其存在CWinThread变量中,以便能够进一步控制线程。

       AxCreateThread()函数和CWinThread:: CreateThread()函数并不是简单地对_beginthreadex()函数进行了一下封装,它还做了一些应用程序框架所需的内部数据的初始化工作,并保证使用正确的C运行库版本,因为在两个函数一开始就要检查环境参数_MT是否已经定义。而且在创建线程过程中还进行了很多检查和测试,保证能够正确产生新的线程,同时在线程创建失败时正确地释放掉已经分配的资源。

    注意事项:

    (1)一般情况下,推荐使用AfxBeginThread()来一次性地创建并启动一个线程,但是也可以通过两步法来创建线程:首先创建CWinThread类的一个对象,然后调用该对象的成员函数CreateThread()来启动该线程。

    (2)MFC支持两类多线程,即工作线程和用户界面线程。用户界面线程经常重载InitInstance()和ExitInstance()函数,用以控制用户界面线程实例的初始化和必要的清理工作。工作者线程一般不使用

    3.线程函数

    (1)工作线程的线程函数:从AfxBeginThread()函数的参数可以看出:

    AFX_THREADPROC pfnThreadProc,//线程函数

     LPVOID pParam,               //传给线程函数的参数

    其中AFX_THREADPROC为一个宏,其定义如下:

    typedef UINT(AFX_CDECL *AFX_THREADPROC)(LPVOID);

    从以上语句,可以得到工作线程的线程函数的形式为:

    UINT ThreadFunc(LPVOID pParm);

    ThreadFunc()函数应返回一个UINT类型的值,用以指明该函数结束的原因。一般情况下,返回0表明执行成功。

    pParam:传递给线程函数的一个32位参数,执行函数将用某种方式解释该值。它可以是数值,或是指向一个结构的指针,甚至可以被忽略。

    (2)用户界面线程的线程函数:从AfxBeginThread()函数的参数可以看出:

    CRuntimeClass* pThreadClass,//从CWinThread派生的类的RUNTIME_CLASS

    即pThreadClass 是指向 CWinThread 的一个导出类的运行时类对象的指针,该导出类定义了被创建的用户界面线程的启动、退出等。

    有了上面的基础,下面来学习线程的创建。

    4.工作线程的创建

    工作线程没有消息机制经常用来完成一些后台工作,如计算、打印、等待、循环等,这样用户就不必因为计算机在从事繁杂而耗时的工作而等待。创建一个工作线程相对比较简单。

    我们用一个实例来演示工作线程的创建。查找N(很大)以内的素数,为了演示效果,N的取值很大(比如:10000等),并在主界面实时动态显示处理结果,并显示处理进度等。

    先说下素数的定义:素数又称质数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数。

    一个数 如果是素数,那么它的所有的因子不超过sqrt(n)(n的平方)那么我们可以用这个性质用判断一个数是否是素数。在此不讨论该算法的复杂度,只是演示效果,望大牛们不要拍砖哈。

    主要程序:

    //.h文件

    UINT ThreadFunc(LPVOID pParm);//线程函数的定义

    bool IsPrime(UINT Number );   //素数判断


    struct threadInfo

    {

        unsigned int nRange;//范围

        HWND        hWnd;//主窗口句柄,用于消息的发送

    };

    private:

    CWinThread *m_pThread;

    //.cpp文件

    //开始

    void CAfxBeginThread1Dlg::OnBnClickedButtonCal()

    {

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

        m_nNum = 1;

        m_List.ResetContent();

        UpdateData(TRUE);

        m_stTip.SetWindowText("");

        if(m_nRange<2)

        {

           AfxMessageBox("查找范围必须是大于的整数!",MB_OK|MB_ICONERROR);

           return;

        }

        GetDlgItem(IDC_BUTTON_CAL)->EnableWindow(FALSE);

        m_Progress.SetPos(0);

        m_Progress.SetRange32(0,m_nRange);

        m_Info.nRange =m_nRange;

        m_Info.hWnd =m_hWnd;

        m_pThread = AfxBeginThread(ThreadFunc,&m_Info);

        if (m_pThread ==NULL)

        {

           AfxMessageBox("启动失败!",MB_OK|MB_ICONERROR);

           return;

        }

    }

     

    UINT ThreadFunc(LPVOID pParm)

    {

        threadInfo *pInfo=(threadInfo*)pParm;

        bool bResult = false;

        for (inti =2;i<=pInfo->nRange;i++)

        {

           bResult = IsPrime(i);

           ::SendMessage(pInfo->hWnd,WM_INFO,bResult,i);

           //Sleep(1000);

        }

        //结束

        ::SendMessage(pInfo->hWnd,WM_INFO,0,-1);

        return 0;

    }

     

    //素数判断

    bool IsPrime(UINT nNumber )

    {//定理:如果n不是素数, 则n有满足<d<=sqrt(n)的一个因子d.

        if(nNumber < 2)returnfalse;

        if(nNumber == 2)returntrue;

        for (inti = 3;i*i<=nNumber;i += 2)

        {

            if(nNumber%i == 0)

                return false;

        }

        return true;

    }

     

    //显示消息处理函数

    LRESULT CAfxBeginThread1Dlg::OnMyInfo(WPARAMwParam,LPARAMlParam)

    {

        if (wParam == 0&&lParam == -1)

        {//结束

           m_stTip.SetWindowText("完成");

           GetDlgItem(IDC_BUTTON_CAL)->EnableWindow(TRUE);

        }

        else

        {//是素数

           m_Progress.SetPos(lParam);

           CString str;

           str.Format("%d",lParam);

           m_stTip.SetWindowText(str);

           if (wParam)

           {

               str.Format("%d个",m_nNum);

               GetDlgItem(IDC_STATIC1)->SetWindowText(str);

               str.Format("第%d个:%d",m_nNum++,lParam);

               m_List.AddString(str);

           }  

        }  

        return 0;

    }

    结果预览:

    工程源码下载地址:

    http://download.csdn.net/detail/cbnotes/4923353

    欢迎大家修改和指正。

     

    注意事项:

    (1)该方式的多线程和前面的_beginthreadex方式很想象,一般用于后台的工作执行。

    (2)注意信息的实时显示。

    (3)创建线程时多参数的传递,此处采用结构体的方式。

    5.用户界面线程的创建

    由于用户界面线程含有自己的消息循环,可以处理Windows消息,并可创建和管理诸如窗口和控件等用户界面元素。因此,这种线程较工作线程更为复杂。

    创建用户界面线程的起点是MFCCWinThread类派生一个定制的线程类,而不是调用AfxBeginThead()函数。定制的线程类必须重载InitInstance()函数,该函数用来执行初始化任务,在创建线程时系统将调用InitInstance()函数。最好还要重载ExitInstane()函数,该函数是InitInstance()函数的对应,MFC在删除线程对象之前会调用ExitInstane()函数,以便线程能够在结束后清除自身。

    用户界面线程的创建有两种方法,方法一是首先从CWinThread类派生一个类(必须要用宏DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE对该类进行声明和实现),然后调用AfxBeginThead()创建CWinThread派生类的对象进行初始化,启动线程运行。方法二是先通过构造函数创建类CWinThread的一个对象,然后由程序员调用函数::CreateThread来启动线程。通常CWinThread类的对象在该线程的生存期结束时将自动终止,如果程序员希望自己来控制,则需要将m_bAutoDelete设为FALSE。这样在线程终止之后,CWinThread类对象仍然存在,此时需要手动删除CWinThread对象。

    5.1用户界面线程实例1

         该实例主要演示创建用户界面线程的第一种方法,先从CWinThread类派生一个类,然后调用AfxBeginThead()创建CWinThread派生类的对象进行初始化,启动线程运行。该实例主要演示文件的移动,并实施显示操作的进度。设计到两个线程:文件的读写采用工作线程,进度显示采用用户界面线程。

    主要程序:

    //.h文件

    define  STEPLEN 1024*64     //文件一次读写的进步k

    UINT ThreadFunc(LPVOID pParm);//线程函数的定义:文件复制线程

    CWinThread *pUIThread;//界面线程,用于进度的显示

    CWinThread *pThread//工作线程,用于文件的复制

    CString m_szSrcPath//源文件路径

    CString m_szDesPath//目标文件路径

     

    //.CPP文件

    //文件复制模块:

    void CAfxBeginThead2Dlg::OnBnClickedButtonCopy()

    {

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

        if (m_szDesPath.IsEmpty() ||m_szSrcPath.IsEmpty())

        {

           AfxMessageBox("源文件路径和目标文件路径不能为空!",MB_OK|MB_ICONERROR);

           return;

        }

       //

        GetDlgItem(IDC_BUTTON_COPY)->EnableWindow(FALSE);

        //创建用户界面线程,用于进度的显示

        pUIThread=AfxBeginThread(RUNTIME_CLASS(CcbCopyFile));

        if (pUIThread ==NULL)

        {

           AfxMessageBox("用户界面线程启动失败!",MB_OK|MB_ICONERROR);

           GetDlgItem(IDC_BUTTON_COPY)->EnableWindow(TRUE);

           return;

        }

        //传递参数

       pUIThread->PostThreadMessage(WM_THREADINFO,0,(LPARAM)m_szSrcPath.GetBuffer(0));

    pUIThread->PostThreadMessage(WM_THREADINFO,1,(LPARAM)m_szDesPath.GetBuffer(0));

        //创建工作线程,用于文件的复制

        pThread=AfxBeginThread(ThreadFunc,this);

        if (pThread ==NULL)

        {

           AfxMessageBox("工作线程启动失败!",MB_OK|MB_ICONERROR);

           GetDlgItem(IDC_BUTTON_COPY)->EnableWindow(TRUE);

           return;

        }

        SetTimer(1,1000,NULL);//速度统计

        SetTimer(2,100,NULL);//操作计时

        m_stTip.SetWindowText("进行中...");

        pUIThread->PostThreadMessage(WM_THREADINFO,2,1);//启动

    }

     

    //文件复制线程

    UINT ThreadFunc(LPVOID pParm)

    {

        CAfxBeginThead2Dlg*pInfo=(CAfxBeginThead2Dlg*)pParm;

       //打开源文件,得到文件的大小,并一块一块的读取

        CFile ReadFile;

        BOOL bOpen = ReadFile.Open(pInfo->m_szSrcPath,CFile::modeRead);

        if(!bOpen)

        {

           AfxMessageBox(pInfo->m_szSrcPath +_T("  :文件打开失败!"),MB_ICONERROR|MB_OK);

           pInfo->m_stTip.SetWindowText("复制【失败】!");

           pInfo->GetDlgItem(IDC_BUTTON_COPY)->EnableWindow(TRUE);

           return 1;

        }

        //得到文件的大小,用于计算进度

        DWORD dwTotalSize= ReadFile.GetLength();

        DWORD dwCompleteSize= 0;//已完成的大小

        //计算文件去读的步长

        DWORD dwStep = STEPLEN > dwTotalSize? dwTotalSize : STEPLEN;

        //数据缓冲区

        char *pBuf =newchar[dwStep+1];

        memset(pBuf,0x00,dwStep+1);

        DWORD dwRead = dwStep;

       //创建目标文件,若目标文件存在则清空

        CFile WriteFile;

        bOpen = WriteFile.Open( pInfo->m_szDesPath,CFile::modeCreate |CFile::modeWrite);

        if(!bOpen)

        {

           AfxMessageBox(pInfo->m_szDesPath +_T("  :文件打开失败!"),MB_ICONERROR|MB_OK);

           pInfo->m_stTip.SetWindowText("复制【失败】!");

           pInfo->GetDlgItem(IDC_BUTTON_COPY)->EnableWindow(TRUE);

           return 2;

        }

        //文件的复制:从源文件去读取数据,并写入到目标文件中

        while( (dwRead =ReadFile.Read(pBuf,dwStep))> 0 )

        {//读取源文件,一次一块

           //将读取的数据写入目标文件中

           WriteFile.Write(pBuf,dwRead);

           dwCompleteSize += dwRead;

           pInfo->m_nSpeed+=dwRead;

           //更新进度

           pInfo->pUIThread->PostThreadMessage(WM_THREADINFO,3, (LPARAM)int((dwCompleteSize*1.0/dwTotalSize)*100));

        }

        //完成

        delete pBuf;

        //关闭文件

        ReadFile.Close();

        WriteFile.Close();

        //发送结束消息,用于关闭进度显示模块

        pInfo->pUIThread->PostThreadMessage(WM_THREADINFO,10, 1);

        pInfo->KillTimer(1);

        pInfo->KillTimer(2);

        pInfo->m_stTip.SetWindowText("复制完成!");

        //使能复制按钮,以便可以继续进行

        pInfo->GetDlgItem(IDC_BUTTON_COPY)->EnableWindow(TRUE);

        return 0;

    }

    //用户界面线程类:派生于CWinThread类

    //文件复制模块:头文件

     

    class CcbCopyFile : publicCWinThread

    {

        DECLARE_DYNCREATE(CcbCopyFile)

     

    protected:

        CcbCopyFile();           // 动态创建所使用的受保护的构造函数

        virtual ~CcbCopyFile();

        CString m_szSrcPath,m_szDesPath;

     

    public:

        CCopyFileDlg *m_pProgressDlg;//进度界面

        virtual BOOL InitInstance();

        virtual int  ExitInstance();

        afx_msg void OnThreadInfo(WPARAMwParam,LPARAMlParam);

    protected:

        DECLARE_MESSAGE_MAP()

    };

    ===================================================================

    // cbCopyFile.cpp : 实现文件

    //

    #include "stdafx.h"

    #include "AfxBeginThead2.h"

    #include "cbCopyFile.h"


    // CcbCopyFile

     

    IMPLEMENT_DYNCREATE(CcbCopyFile,CWinThread)

     

    CcbCopyFile::CcbCopyFile()

    {

        m_pProgressDlg = NULL;

    }

     

    CcbCopyFile::~CcbCopyFile()

    {

    }

     

    BOOL CcbCopyFile::InitInstance()

    {

        // TODO: 在此执行任意逐线程初始化

        return TRUE;

    }

     

    int CcbCopyFile::ExitInstance()

    {

        // TODO: 在此执行任意逐线程清理

        return CWinThread::ExitInstance();

    }

     

    BEGIN_MESSAGE_MAP(CcbCopyFile,CWinThread)

        ON_THREAD_MESSAGE(WM_THREADINFO,&CcbCopyFile::OnThreadInfo)

    END_MESSAGE_MAP()

     

    // CcbCopyFile 消息处理程序

     

    //显示消息处理函数

    void CcbCopyFile::OnThreadInfo(WPARAMwParam,LPARAMlParam)

    {

        if (wParam == 0)

        {//源文件路径参数

           m_szSrcPath.Format("%s",lParam);

           //AfxMessageBox(m_szSrcPath);

        }

        else if (wParam == 1)

        {//目标文件路径参数

           m_szDesPath.Format("%s",lParam);

           //AfxMessageBox(m_szDesPath);

        }

        else if (wParam == 2)

        {//启动

           m_pProgressDlg = newCCopyFileDlg;

           m_pProgressDlg->Create(IDD_DIALOG1);

           m_pProgressDlg->m_szSrcPath=m_szSrcPath;

           m_pProgressDlg->m_szDesPath=m_szDesPath;

           m_pProgressDlg->UpdateData(FALSE);

           m_pProgressDlg->ShowWindow(TRUE);

        }

        else if (wParam == 3)

        {//进度

           m_pProgressDlg->m_Progress.SetPos(lParam);

        }

        else if (wParam == 4)

        {//速度

           m_pProgressDlg->UpdateSpeed(lParam);

        }

        else if (wParam == 5)

        {//时间

           float *p = (float *)lParam;

           m_pProgressDlg->UpdateTime(*p);

        }

        else

        {//完成

           m_pProgressDlg->OnCancel();

        }

        //return 0;

    }

    结果预览:

    工程源码下载地址:

    http://download.csdn.net/detail/cbnotes/4956549

    欢迎大家修改和指正。

     

    注意事项:

    (1)该实例源码比较多,所以上面只贴出了重要的部分,建议下载整个工程源码下来学习和研究(地址见上)。

    (2)该实例主要演示了文件复制,采用了工作线程和用户界面线程相配合。提供了实时的进度显示、实时复制速度显示和时间显示。功能还是比较实用,只要稍加修改做成一个复制模块(dll用于自己的程序中,还是非常实用。对不喜欢采用CopyFile/CopyFileEx函数的朋友是一个不错的选择。

    (3)注意在工作线程中,响应消息的方式,消息映射和平时的不一样,主要采用ON_THREAD_MESSAGE而不是ON _MESSAGE。

    (4)注意工作线程创建中,传递给线程函数的参数为this,即 pThread=AfxBeginThread(ThreadFunc,this);//即传递的是对象的地址。这对于要传递很多参数的是一个不错的选择。

    消息响应函数的格式为:void OnThreadInfo(WPARAMwParam,LPARAM lParam);

    注意返回类型必须为void

    (5)该实例还有一个不完善的地方,就是复制过程中按“取消”的处理,该实例中还没有实现,望有心的朋友可以实现它,大家多多思考和动手,对你一定有很好的帮助的。

    (6)用户界面线程和程序的主线程很相像,能处理各种消息。

    5.2用户界面线程实例2

    该实例主要演示创建用户界面线程的第二种方法,先从CWinThread类派生一个类,然后调用CreateThread创建CWinThread派生类的对象进行初始化,启动线程运行。该实例主要演示手气测试,设计到两个用户界面线程:数字输入线程和结果判断线程。

    主要程序:

    //主线程

    CInputThread *m_pInputThread;//数字输入线程

    CResultThread  *m_pResultThread;//结果判断线程

    //测试

    void CAfxBeginThead3Dlg::OnBnClickedButtonTest()

    {

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

        m_pInputThread = newCInputThread;

        m_pInputThread->CreateThread(CREATE_SUSPENDED);

     

        m_pResultThread = newCResultThread;

        m_pResultThread->CreateThread(CREATE_SUSPENDED);

        m_pResultThread->m_hWnd=m_hWnd;

        m_pInputThread->m_pResultThread=m_pResultThread;

        m_pInputThread->ResumeThread();//运行

        m_pResultThread->ResumeThread();

        m_nTimes++;

    //  UpdateInfo();

    }

     

    LRESULT CAfxBeginThead3Dlg::OnMessage(WPARAMwParam,LPARAMlParam)

    {

        if(lParam == 1)

        {//成功一次

           m_nSucess++;

        }

        UpdateInfo();

        if(wParam == 1)

        {//再测一次

           OnBnClickedButtonTest();

        }

        return 0;

    }

    // 更新信息

    void CAfxBeginThead3Dlg::UpdateInfo(void)

    {

        CString str;

        str.Format("统计:%d/%d",m_nSucess,m_nTimes);

        GetDlgItem(IDC_STATIC1)->SetWindowText(str);

    }

    //数字输入线程

    CResultThread  *m_pResultThread;//结果判断线程

    CInputDlg m_InputDlg;//输入对话框

    BOOL CInputThread::InitInstance()

    {

        // TODO: 在此执行任意逐线程初始化

        m_InputDlg.DoModal();

        return TRUE;

    }

    int CInputThread::Run()

    {

        // TODO: 在此添加专用代码和/或调用基类

       m_pResultThread->PostThreadMessage(WM_THREADMESSAGE,0,m_InputDlg.m_nInput);

        return CWinThread::Run();

    }

    //结果判断线程

    #define  WM_THREADMESSAGE WM_USER+100 //输入数字线程发送的消息,用于结果判断

    #define WM_MESSAGEWM_USER+200//向主线程发送消息,用于返回相关信息

    BEGIN_MESSAGE_MAP(CResultThread,CWinThread)

        ON_THREAD_MESSAGE(WM_THREADMESSAGE,&CResultThread::OnThreadMessage)

    END_MESSAGE_MAP()

     

    //显示消息处理函数

    void CResultThread::OnThreadMessage(WPARAMwParam,LPARAMlParam)

    {

        if (wParam == 0)

        {  

           bool bSucess = false;

           CString str;

           int  nLuckNum = GetLuckNum();

           if (lParam ==nLuckNum)

           {

               bSucess = true;

               str.Format("恭喜,手气不错哦!\n=============\n你测试的数字为【%d】\n当前的幸运数字为【%d】\n再测一次吧?",lParam,nLuckNum);

           }

           else

           {

               bSucess = false;

               str.Format("很遗憾,差一点点哦!\n=============\n你测试的数字为【%d】\n当前的幸运数字为【%d】\n再测一次吧?",lParam,nLuckNum);

           }

           if(AfxMessageBox(str,MB_YESNO|MB_DEFBUTTON1|MB_ICONINFORMATION)==IDYES)

           {

               ::SendMessage(m_hWnd,WM_MESSAGE,1,bSucess);//发送消息

           }

           else

           {

               ::SendMessage(m_hWnd,WM_MESSAGE,0,bSucess);//发送消息

           }

        }

        else

        {

           ;

        }

    }

     

    // 得到幸运数字

    int CResultThread::GetLuckNum(void)

    {

        srand((unsigned)time(NULL));

        return rand()%10;

    }

    结果预览:

    工程源码下载地址:

    http://download.csdn.net/detail/cbnotes/4958041

    欢迎大家修改和指正。

     

    注意事项:

    (1)从CWinThread类派生的类的构造函数和解析函数默认是protected,要采用第二种方法则要修改为public,否则将出错。

    (2)注意线程参数的传递方法,和前面不一样的。即创建线程时先设置为CREATE_SUSPENDED(挂起),然后设置相关参数,然后再启动线程,具体可以参考程序。

    m_pResultThread= new CResultThread;

          m_pResultThread->CreateThread(CREATE_SUSPENDED);//创建线程时先挂起

          m_pResultThread->m_hWnd =m_hWnd;//然后相关设置参数

          m_pResultThread->ResumeThread();//再运行

    (3)注意CWinThread派生类中Run()函数的重载。仔细想想下面的程序的执行原理,为什么对话框结束后就会执行此处。如果将对话框设置为非模式对话框,还会正常吗?

    int CInputThread::Run()

    {

              // TODO: 在此添加专用代码和/或调用基类

              m_pResultThread->PostThreadMessage(WM_THREADMESSAGE,0,m_InputDlg.m_nInput);

              return CWinThread::Run();

    }


     

     

    展开全文
  • MFC线程获取窗口

    2014-06-30 14:55:24
    今天写多线程函数,顺便问下了下
  • MFC 工作线程和界面线程

    千次阅读 2014-06-16 17:26:34
    MFC线程的创建 1.MFC线程简介 MFC对多线程进行了一层简单的封装,在Visual C++中每个线程都是从CWinThread类继承而来的。每一个应用程序的执行都有一个主线程,这个主线程也是从CWinThread类继承而来的。...
  • MFC线程线程同步

    2015-05-06 10:03:56
    ... MFC中有两类线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。  工作者线程没有消息机制,通常
  • VC++ MFC线程线程同步

    千次阅读 2010-12-26 21:46:00
    VC++ MFC线程线程同步 关键词: MFC线程线程同步
  • MFC 时间线程

    2019-03-15 10:06:56
    mfc的界面中添加动态时间:系统时间(动态),软件运行时间(动态) 先在.h头文件中定义线程(可用定时器OnTime来替换线程); public: static DWORD WINAPI threadFuncTime(LPVOID threadTime);//时间线程 ...
  • C++ 线程 获取线程id

    千次阅读 2020-03-11 13:51:33
    void foo() { std::thread::id this_id = std::this_thread::get_id(); unsigned int t = *(unsigned int*)&this_id;// threadid 转成 unsigned int unsigned int threadid = t; g_display_mutex.lock(); std::cout...
  • MFC线程的创建,包括工作线程和用户界面线程

    万次阅读 多人点赞 2013-01-04 16:41:40
    MFC线程的创建 1.MFC线程简介 MFC对多线程进行了一层简单的封装,在Visual C++中每个线程都是从CWinThread类继承而来的。每一个应用程序的执行都有一个主线程,这个主线程也是从CWinThread类继承而来的。可以...
  • MFC线程线程同步

    2012-12-14 10:22:09
    MFC线程线程同步 一、MFC对多线程编程的支持  MFC中有两类线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。  ...
  • MFC线程编程

    2015-11-17 14:36:53
     新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,代码如下: void CSingleThreadDlg::...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,863
精华内容 3,145
关键字:

mfc获取线程id