C++/MFC中多線程使用


一。創建線程的三種方式

1.CreateThread (windows中vc++)

CreateThread(
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, //線程屬性
    _In_ SIZE_T dwStackSize, //棧空間大小
    _In_ LPTHREAD_START_ROUTINE lpStartAddress, //線程執行函數地址
    _In_opt_ __drv_aliasesMem LPVOID lpParameter, //傳遞參數
    _In_ DWORD dwCreationFlags, //標志,可以選擇掛起
    _Out_opt_ LPDWORD lpThreadId //線程id
    );
 1 DWORD WINAPI ThreadProc(LPVOID lpParameter)
 2 {
 3     int a = (int)lpParameter;
 4     CString str;
 5     str.Format(_T("%d"),a);
 6     AfxMessageBox(str);
 7     return 0;
 8 }
 9 void CSegDlg::OnBnClickedstop()
10 {
11     // TODO: 在此添加控件通知處理程序代碼
12     DWORD dwThreadId = 0; //線程id
13     HANDLE hThread=CreateThread(NULL, 0, ThreadProc, (LPVOID)123, 0, &dwThreadId); //返回線程句柄
14     //關閉句柄,線程結束后釋放
15     CloseHandle(hThread);
16 }

2.AfxBeginThread(MFC)

CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,
	int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0,
	DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);  //創建工作線程,工作線程用來處理一些邏輯
CWinThread* AFXAPI AfxBeginThread(CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL); //創建界面線程,界面線程會有消息循環
 1 UINT _cdecl ThreadProc(LPVOID lpParameter)
 2 {
 3     int a = (int)lpParameter;
 4     CString str;
 5     str.Format(_T("%d"), a);
 6     AfxMessageBox(str);
 7     return 0;
 8 }
 9 void CSegDlg::OnBnClickedstop()
10 {
11     // TODO: 在此添加控件通知處理程序代碼
12     CWinThread *pThread=AfxBeginThread(ThreadProc, (LPVOID)456);
13 
14 }

 3._beginthread

 

二。子線程使用主線程參數

1.子線程對應於一個普通函數,不能被簡單的聲明成主對話框類的成員函數,因此不能使用主對話框(主線程)的參數,需要在創建線程時,將主對話框類對象的指針傳遞給子線程。子線程通過指針去訪問主線程的變量。

 1 UINT _cdecl ThreadProc(LPVOID lpParameter)
 2 {
 3     CSegDlg* pSegDlg = (CSegDlg *)lpParameter; //轉換為主對話框類的指針
 4     int a = pSegDlg->num;
 5     CString str;
 6     str.Format(_T("%d"), a);
 7     AfxMessageBox(str);
 8     return 0;
 9 }
10 void CSegDlg::OnBnClickedstop()
11 {
12     num = 100; //成員變量
13     CWinThread *pThread=AfxBeginThread(ThreadProc, this);
14 }

 2.如果一定要將子線程函數聲明為類成員函數,需要定義為靜態成員函數

 1 UINT _cdecl CSegDlg::ThreadProc(LPVOID lpParameter) //static函數
 2 {
 3     CSegDlg* pSegDlg = (CSegDlg *)lpParameter; //仍然需要傳遞對象指針,因為static關鍵詞沒有this指針
 4     int a = pSegDlg->num;  
 5     CString str;
 6     str.Format(_T("%d"), a);
 7     AfxMessageBox(str);
 8     return 0;
 9 }
10 void CSegDlg::OnBnClickedstop()
11 {
12     num = 100;
13     CWinThread *pThread=AfxBeginThread(ThreadProc, this);
14 }

 

三。創建界面線程。

1.如同主對話框創建時一樣,會有一個應用程序類App,如果需要再創建一個線程來管理對話框,需要創建自定義類,繼承於CWinThread類。

2.創建好的App類和對話框類如下圖所示。

 

 需要在CUIThreadApp中添加CTestDlg.h

3.重寫CUIThreadApp中的InitInstance()和ExitInstance()函數。進行對話框的創建和資源的釋放。

 1 BOOL CUIThreadApp::InitInstance()
 2 {
 3     // TODO:    在此執行任意逐線程初始化
 4     /*CTestDlg dlg;  //創建模態對話框
 5     dlg.DoModal(); //阻塞
 6     return FALSE; //return FALSE會釋放線程
 7     */
 8 
 9 
10     CTestDlg* dlg = new CTestDlg();
11     dlg->Create(IDD_DIALOG1);
12     dlg->ShowWindow(SW_SHOW);
13     dlg->RunModalLoop();  // 讓非模態對話框處於循環
14     return FALSE; //return FALSE釋放線程
15 }

4.在對話框對象中進行界面線程的創建。

1 void CmfcThreadDlg::OnBnClickedOk()
2 {
3     // TODO: 在此添加控件通知處理程序代碼
4     AfxBeginThread(RUNTIME_CLASS(CUIThreadApp));
5 }

 

四。線程掛起(暫停)、恢復、中止

1.SuspendThread

DWORD
WINAPI
SuspendThread(
_In_ HANDLE hThread
);

2.ResumeThread

DWORD
WINAPI
ResumeThread(
_In_ HANDLE hThread
);

 1 HANDLE hThread;
 2 void CmfcThreadDlg::OnBnClickedOk()
 3 {
 4     CWinThread* pThread = AfxBeginThread(ThreadProc, this);
 5     hThread = pThread->m_hThread; //獲取線程句柄
 6 }
 7 
 8 void CmfcThreadDlg::OnBnClickedbtnsuspend()
 9 {
10     SuspendThread(hThread);
11 }
12 
13 void CmfcThreadDlg::OnBnClickedbtnresume()
14 {
15     ResumeThread(hThread);
16 }

 

3.線程退出

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM