C++ AfxBeginThread的介绍/基本用法
AfxBeginThread 用户界面线程和工作者线程都是由AfxBeginThread创建的。现在,考察该函数:MFC提供了两个重载版的AfxBeginThread,一个用于用户界面线程,另一个用于工作者线程,分别有如下的原型和过程: 用户界面线程的AfxBeginThread CWinThread* AFXAPI AfxBeginThread( CRuntimeClass* pThreadClass,int nPriority,UINT nStackSize,DWORD dwCreateFlags,LPSECURITY_ATTRIBUTES lpSecurityAttrs) 其中: 工作者线程的AfxBeginThread CWinThread* AFXAPI AfxBeginThread( AFX_THREADPROC pfnThreadProc,LPVOID pParam,LPSECURITY_ATTRIBUTES lpSecurityAttrs) 其中: 附录A: 结束线程的两种方式 面会详细的向你解释要结束线程的两种方式 1 : 这是最简单的方式,也就是让线程函数执行完成,此时线程正常结束.它会返回一个值,一般0是成功结束, 当然你可以定义自己的认为合适的值来代表线程成功执行.在线程内调用AfxEndThread将会直接结束线程,此时线程的一切资源都会被回收. 2 : 如果你想让别一个线程B来结束线程A,那么,你就需要在这两个线程中传递信息.不管是工作者线程还是界面线程,如果你想在线程结束后得到它的确结果,那么你可以调用 ::GetExitCodeThread函数 还是老师的那个项目,以前由于计算量太大,导致程序经常出现假死的现象,因为程序只有一个线程,该线程主要用于处理计算上了,而对于消息队列的响应被忽略了。因此解决的办法就是用两个线程,一个线程用于计算,一个线程用于处理消息。 到网上找了一些资料,发现在MFC中把线程分为两类,一类为界面线程,一类为工作线程。两者的区别在于前都能够处理消息响应,而后者则不能。对于该项目来说,只要把计算的过程放到一个工作线程里来进行就可以了。 现在先试一下,我新建了一个对话框,上面添加两个按钮,一个是start 一个是dialog。前者用于开始计算,而后者则弹出一个消息框。然后向该对话框里面添加一个死循环的函数 UINT CMultithreadDlg::jisuan(LPVOID lpParam) { int i = 1; for (;;) { i+=i; } return 0; } 然后在start按钮的响应函数上添加上jisuan(NULL);即可,现在运行程序,按下start按钮后,可以看到CPU使用率涨到了100%,这个时候再按dialog按钮无反应,拖动关闭窗口均无效。这就是前面提到的假死现象(实际上是真死,因为死循环了,如果不是死循环,而只是计算量太大才是假死)。 下面用多线程的方法来解决,在start按钮的响应函数改为 CWinThread* mythread = AfxBeginThread( jisuan,NULL,THREAD_PRIORITY_NORMAL,NULL ); 运行,结果发现有错error C2665: 'AfxBeginThread' : none of the 2 overloads can convert parameter 1 from type 'unsigned int (void *)' Generating Code... 其实上面的那个AfxBeginThread,除前面两个参数外,后面的都是默认参数,可以省略。而必须有的这两个参数,一个是线程函数的指针,一个是传递给这个函数的参数。实际中我们经常这样用 AfxBeginThread(ThreadProc,this);//把this传过去,就可以调用类的成员了. 这样线程函数就可以使用和操作类的成员了。千万要注意线程函数是静态类函数成员。 线程是创建了,但是如果中途要暂停该怎么做呢? 我们在创建线程的时候获得了一个CWinThread的指针,这是一个指向线程对象的指针,CWinThread类里面就有暂停与恢复的函数,下面我就演示一下。 在原来的程序上进行改动。向对话框类里面添加一个CWinThread* 的成员变量,不用初始化为NULL,这样会报错的,因为它只能通过AfxBeginThread函数获得。把start里面的声明去掉。 具体 总结如下 AfxBeginThread创建线程 1.声明线程函数: UINT StartDownloadThread(LPVOID pParam); // 下载线程, CWinThread* m_pThread; // 线程对象指针 // 创建多线程 void CMyDownloadDlg::CreateThread(CDLoadThread* pDloadThread) { // 创建响应线程,启动线程函数 m_pThread = AfxBeginThread(StartDownloadThread,(LPVOID)pDloadThread); if(NULL == m_pThread) { TRACE("创建新的线程出错!n"); return; } } 3.定义线程函数 UINT StartDownloadThread(LPVOID pParam) { // 为每个线程(任务数)创建一个套接字来完成下载 CDLoadThread* pThis = (CDLoadThread*)pParam; LONG indexTask = 0; //indexTask = pThis->m_indexThread; LONG indextNum = pThis->httpDload.m_index; InterlockedIncrement(&pThis->httpDload.m_index); // 互斥方法访问共享资源,防止冲突 int ret = pThis->httpDload.CreateThreadFunc(indexTask,indextNum); //TRACE("线程%d已成功完成!%dn",index,ret); return 0; } 以上所述就是本文的全部内容了,希望大家能够喜欢。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |