一。創建線程的三種方式
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.線程退出