多線程編程mfc
㈠ MFC多線程
我就比較喜歡用多線程, 最簡單的想法就是效率高, 比如, 我們只用一個主線程在一個程序里, 每一個時刻都在做一件事情; 而如果我們開辟了多個線程的話, 就可以在同一時刻做多件事情而互不幹擾, 各自完成各自的工作。
多線程就好比多任務的操作系統, 同一時刻我們既可以聽音樂又可以上網, 而單線程就好比單任務的, 我們需要聽完音樂再去上網, 這樣花費的時間久很多了。
再比如說, 你的程序里需要不斷的更新某項數據, 那你就可以為它開辟一個線程, 讓它無限循環著每隔一段時間就在後台進行一次更新操作, 而主線程仍跟用戶不間斷的交互著, 線程是不是很方便呢?
我是這么理解的。
線程還有個地方是比較通用的, 比如我們的程序中, 有個功能的實現比較耗時, 比如讀取龐大的資料庫中的信息,並對數據進行計算等操作, 這個耗時比較大, 那麼我們就要給它開辟一個線程, 讓它在後台進行, 主線程正跟用戶做著其他事情的時候, 這個線程便悄悄從後台對數據進行了處理了, 這樣用戶就不必乾等著了,感覺不到你程序運行的慢了; 一般超過5秒的等待時間都要為它開辟一個線程。
就說這么多了~~
㈡ MFC多線程編程
可能是執行的過快造成的吧。
建議如下:
1. 定義兩個信號量CEvent,初始化為非信號;
2. 在AfxBeginThread()創建線程後,加入短暫的休眠Sleep()函數讓線程有機會初始化。
3. 在Sleep函數後用WaitForSingleObject等待對應線程的准備就緒信號量置位
4. 在線程執行體內,准備就緒後,添加置位對應的信號量的語句。
這樣通過檢測信號量可以使得兩個線程都准備就緒,然後再開始通信。
另外,請注意線程中循環體內的休眠時間,理應比通信速度要快,才能有效檢測。其實最好的方法就是通過信號量等對象來控制多線程間的非同步時序關系。
㈢ 怎麼在基於對話框的MFC程序中實現多線程
基於MFC的對話框程序加啟動進度條(轉)
對於比較大的程序,在啟動的時候都會顯示一個畫面,以告訴用戶程序正在載入,或者顯示一些關於軟體的信息,如Visual C++,Word, PhotoShop等。
這些啟動畫面在Visual C++中怎麼實現呢?對於文檔/視圖結構的程序,可以直接使用VC提供的SplashWnd組件。可是在基於對話框的程序卻不能使用SplashWnd組件。因此只能自己來實現此功能。
因為顯示啟動畫面的同時還要進行程序的載入工作,所以要用到多線程。MFC區分了兩種不同類型的多線程:用戶界面(UI)線程和工作者線程。兩者的區別是UI線程有消息循環,而工作者線程沒有,UI線程能夠創建窗口並處理發送給窗口的消息。工作者線程用來執行後台任務,這些後台任務不直接接受用戶輸入,因此不需要窗口和消息循環。 因為這里要顯示一個畫面,所以要使用UI線程。
下面結合我做的一個小軟體「實用鬧鍾」來說明如何為對話框程序製作啟動畫面。
打開Visual C++建立一個對話框工程Page.
首先准備一副點陣圖資源插入到工程中,作為啟動時顯示的畫面。再插入一個對話框,設置ID為IDD_SPLASH。在上面放一個picture控制項,類型設為」Bitmap」,圖象選擇剛才插入的點陣圖。
設置對話框的Style為Popup,Border 為None,去掉Title Bar屬性,並調整對話框的大小與點陣圖等大,這樣對話框顯示的時候,你看到的只是圖片。打開 ClassWizard為此對話框建立一個新類CSplashDlg, 基類為CDialog.
UI線程是由一個動態可創建的類來控制,該類是從CWinThread派生的,非常類似從CWinApp派生的一個應用程序類.打開ClassWizard建立一個由CWinThread派生的類----CSplashThread,在SplashThread.h 中加入 #include"SplashDlg.h",並添加一個protected型指針變數:
CSplashDlg* m_pSplashDlg; //聲明一個對話框指針
下面我們將在UI線程的InitInstance()函數中調用剛才創建的對話框並顯示。
BOOL CSplashThread::InitInstance()
{
::AttachThreadInput(m_nThreadID, AfxGetApp()->m_nThreadID, TRUE );
//:通常系統內的每個線程都有自己的輸入隊列。本函數允許線程和進程共享輸入隊列。連接了線程後,輸入焦點、窗口激活、滑鼠捕獲、鍵盤狀態以及輸入隊列狀態都會進入共享狀態 . (這個函數可以不用)
m_pSplashDlg=new CSplashDlg;
m_pSplashDlg->SetEnable(true);
m_pSplashDlg->Create(IDD_SPLASH);
m_pSplashDlg->ShowWindow(SW_SHOW);
return true;
}
為CSplashThread類添加一個函數HideSplash(), 用來隱藏啟動畫面(即關閉對話框)
void CSplashThread::HideSplash()
{
m_pSplashDlg->SendMessage(WM_CLOSE);
}
在ExitInstance()中釋放資源:
int CSplashThread::ExitInstance()
{
m_pSplashDlg->DestroyWindow();
delete m_pSplashDlg;
return CWinThread::ExitInstance();
}
在應用程序類CPageApp中包含頭文件: #include 「SplashThread.h」
並添加兩個變數:
public: //設為pulic類型,是為了在其他類中能夠訪問
CSplashThread* pSplashThread;
CSplashDlg* m_pSplashDlg;
在InitInstance()中啟動UI線程:
pSplashThread = (CSplashThread*) AfxBeginThread(
RUNTIME_CLASS(CSplashThread),
THREAD_PRIORITY_NORMAL,
0, CREATE_SUSPENDED);
ASSERT(pSplashThread->IsKindOf(RUNTIME_CLASS(CSplashThread)));
pSplashThread->ResumeThread();
Sleep(1);
為了讓程序一起動就顯示啟動畫面,這段代碼應該放在InitInstance()最開頭的地方.
啟動畫面是顯示了,可是結束代碼應該放在什麼地方呢?如果放在InitInstance()的CPageDlg dlg; m_pMainWnd = &dlg; 後面,即在構造了主對話框之後隱藏啟動畫面, 程序運行時會發現,啟動畫面結束後,還要等一會才能顯示出主對話框,這樣就達不到啟動畫面應有的效果. 最好應該在即將顯示主對話框的時候隱藏啟動畫面. 我的這個軟體中在主對話框中定義了5個子對話框類的對象,分別是page1,page2,…page5.
程序啟動時的流程如下:
Page1構造 --->Page2構造 --->Page3構造---> Page4構造---> Page5構造---> 主對話框構造 --->主對話框初始化---> Page1初始化---> Page2初始化 --->Page3初始化 Page4初始化---> Page5初始化
由此可見,啟動畫面結束的最好地方應該是在 page5的初始化函數中
BOOL CPage5::OnInitDialog()
{
CDialog::OnInitDialog();
if ( ((CPageApp*)AfxGetApp())->pSplashThread != NULL)
((CPageApp*)AfxGetApp())->pSplashThread->HideSplash();
return TRUE;
}
到此,一個對話框程序的啟動畫面就這樣完成了.由於是用對話框作為啟動畫面,所以你可以你可以發揮你的想像力,在對話框上設計出豐富多才的效果來,比如加上Flash,Gif動畫等.
㈣ mfc創建線程的三種方法
MFC中有兩類線程,分別稱之為工作者線程和用戶界面線程。二者的主要區別在於工作者線程沒有消息循環,而用戶界面線程有自己的消息隊列和消息循環。
工作者線程沒有消息機制,通常用來執行後台計算和維護任務,如冗長的計算過程,列印機的後台列印等。用戶界面線程一般用於處理獨立於其他線程執行之外的用戶輸入,響應用戶及系統所產生的事件和消息等。但對於Win32的API編程而言,這兩種線程是沒有區別的,它們都只需線程的啟動地址即可啟動線程來執行任務
1、WIN的API函數CreateThread
HANDLE CreateThread(
LPSECURITY_ATTRIBUTESlpThreadAttributes, // SD
DWORDdwStackSize, // initial stack size
LPTHREAD_START_ROUTINElpStartAddress, // thread function
LPVOIDlpParameter, // thread argument
DWORDdwCreationFlags, // creation option
LPDWORDlpThreadId // thread identifier
);
//lpThreadAttributes:指向SECURITY_ATTRIBUTES型態的結構的指針。在Windows 98中忽略該參數。在Windows NT中,它被設為NULL,表示使用預設值。
dwStackSize,線程堆棧大小,一般=0,在任何情況下,Windows根據需要動態延長堆棧的大小。
lpStartAddress,指向線程函數的指針,形式:@函數名,函數名稱沒有限制,但是必須以下列形式聲明:
DWORD WINAPI ThreadProc (LPVOID lpParam) ,格式不正確將無法調用成功。
lpParameter:向線程函數傳遞的參數,是一個指向結構的指針,不需傳遞參數時,為NULL。
dwCreationFlags :線程標志,可取值如下
(1)CREATE_SUSPENDED-----創建一個掛起的線程,
(2)0---------------------------------表示創建後立即激活。
lpThreadId:保存新線程的id。
2、MFC的全局函數AfxBeginThread
CWinThread* AfxBeginThread( AFX_THREADPROCpfnThreadProc, LPVOIDpParam, intnPriority= THREAD_PRIORITY_NORMAL, UINTnStackSize= 0, DWORDdwCreateFlags= 0, LPSECURITY_ATTRIBUTESlpSecurityAttrs= NULL );
//用於創建工作者線程 其中pfnThreadProc指向線程函數 pParam為傳遞給線程函數的參數
CWinThread* AfxBeginThread( CRuntimeClass*pThreadClass, intnPriority= THREAD_PRIORITY_NORMAL, UINTnStackSize= 0, DWORDdwCreateFlags= 0, LPSECURITY_ATTRIBUTESlpSecurityAttrs= NULL );
//用於創建用戶界面線程 其中pThreadClass為CWinThread派生對象的RUNTIME_CLASS
3、MFC的CWinThread類的CreateThreat成員函數
BOOL CreateThread( DWORD dwCreateFlags = 0, UINT nStackSize = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
//CWinThread類支持工作者線程和用戶界面線程 可以將一個CWinThread派生類的CRUNTIMECLASS的指針作為參數傳遞給AfxBeginThread函數以創建一個用戶界面線程 CWinThread類的CreateThread成員函數創建一個調用進程的地址空間中執行的線程
VC 6.0 創建線程的三種方法
CreateThread/ExitThread
_beginthreadex/_endthreadex
AfxBeginThread /AfxEndThread
對以上三種方式的選擇:
1.在使用了MFC的程序中使用AfxBeginThread函數或者CWinThread::CreateThread函數創建線程。
2.在非MFC工程中,如果要創建多線程,建議使用_beginthreadex
3.避免使用CreateThread函數。不使用_beginthread.
4.線程內部退出函數使用與創建函數配套的函數。
㈤ 求大神指導MFC多線程編程。進度條那種就行。我按照網上的例子運行出來
我用的BOOST庫中的線程庫
void CTestBoost::OnBnClickedBtntestboost()
{
// TODO: 在此添加控制項通知處理程序代碼
UINT length = 500;
m_wndProgress.SetRange(0, length);
m_wndProgress.SetStep(1);
m_wndProgress.SetPos(0);
boost::thread t(boost::bind(&CTestBoost::RunTest, this, length));
t.detach();//將子線程和主線程分離,子線程執行完成後自己釋放資源
}
void CTestBoost::RunTest(UINT length)
{
for(size_t i=0;i<length;i++)
{
m_wndProgress.SetPos(i);
Sleep(2);
}
MessageBox(_T("完成"),_T("提示"),MB_ICONINFORMATION);
GetDlgItem(IDC_BTNTESTBOOST)->EnableWindow(TRUE);
runState=0;
}
㈥ MFC多線程編程里有MAIN函數嗎MFC程序就是多線程嗎MFC和多線程的關系是什麼
子線程沒有main函數入口的說法,但在部分工程模式下,允許命名子線程函數為main
MFC程序本身不是多線程
任何win32下的C++程序都支持用戶自定義多線程,MFC也不例外,就是這個關系。
㈦ MFC中的多線程如何實現。和單線程有啥區別
Windows是對線程進行調度,而使用多線程可以實現程序的實時多任務,但同時也增加了程序的復雜性,即要求線程進行同步。
實現線程只需要AfxBeginThread即可
㈧ MFC編程多線程程序設計
就是線程在Sleep(2000)後,就掛起2秒鍾,於是就進入了等待隊列!在2秒後被喚醒,進入CPU的就緒隊列,這樣,只要時間片辦到這個線程,它就執行!
㈨ MFC多線程編程,如何向輔助UI線程中添加控制項消息響應函數
我不知道你說的輔助UI線程,是否是通過AfxBeginThread創建的CWinThread線程。關於消息響應的問題,不知道你是否按照MFC的要求,建立了必要的類,重載了必要的函數。
但我更想說,你這種做法實在太復雜,完全可以在一個線程中完成的事情,何必放在兩個線程里!!只要簡單地在主窗口對話框中,創建一個定時器,就完全可以實現你需要的功能。