明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

多線程技術(shù)在VC中的應(yīng)用

[摘要]山東理工大學(xué) 賈永新 肖愛梅 Visual C++ 6.0 自發(fā)布以來,以其強(qiáng)大的功能及各種新特性受到廣大編程愛好者的青睞。但是要想成為一個(gè)優(yōu)秀的程序員,寫出真正功能強(qiáng)大、能夠快速響應(yīng)且實(shí)用的程序就必須充分利用一項(xiàng)關(guān)鍵技術(shù):多線程。筆者在工作中應(yīng)用這一技術(shù),開發(fā)了一個(gè)定時(shí)關(guān)機(jī)的實(shí)用程序,在此介紹...
山東理工大學(xué) 賈永新 肖愛梅

Visual C++ 6.0 自發(fā)布以來,以其強(qiáng)大的功能及各種新特性受到廣大編程愛好者的青睞。但是要想成為一個(gè)優(yōu)秀的程序員,寫出真正功能強(qiáng)大、能夠快速響應(yīng)且實(shí)用的程序就必須充分利用一項(xiàng)關(guān)鍵技術(shù):多線程。筆者在工作中應(yīng)用這一技術(shù),開發(fā)了一個(gè)定時(shí)關(guān)機(jī)的實(shí)用程序,在此介紹給廣大讀者,借此幫助讀者加深對(duì)這一技術(shù)的理解。

程序的功能

此實(shí)用程序的主要功能是實(shí)現(xiàn)定時(shí)關(guān)機(jī),同時(shí)也提供了輔助功能:隨時(shí)關(guān)機(jī)、重新啟動(dòng)、注銷以及動(dòng)態(tài)時(shí)鐘。如果設(shè)置的時(shí)間不對(duì),可以隨時(shí)更改。這些功能的具體實(shí)現(xiàn)采用了多線程技術(shù)。

功能的實(shí)現(xiàn)

1.線程的定義

本例中單獨(dú)設(shè)置了一個(gè)線程監(jiān)視當(dāng)前時(shí)間,在Visual C++中線程的簡(jiǎn)單調(diào)用語句為:AfxBegin

-Thread(ProcName, param, Priority),第一個(gè)參數(shù)是線程函數(shù)名,param是準(zhǔn)備傳送給線程的任意32位值,最后一個(gè)是線程的優(yōu)先級(jí)(可用常量表示)。這里先定義一個(gè)線程函數(shù):

UINT timeThreadProc(LPVOID pParam) //定義線程,必須照此格式

{

CTime gt; //定義時(shí)間變量

int hh,mm,ss; //為存儲(chǔ)時(shí)間定義整型變量

do //判斷時(shí)間的循環(huán)

{

gt=CTime::GetCurrentTime();

//提取當(dāng)前時(shí)間

hh=gt.GetHour(); //分別提取時(shí)、分、秒 mm=gt.GetMinute();

ss=gt.GetSecond();

} while ((h!=hh) (m!=mm) (s!=ss));

//判斷當(dāng)前時(shí)間

flag=0; //置狀態(tài)標(biāo)志

ExitWindowsEx(EWX_SHUTDOWN,0);

//關(guān)閉計(jì)算機(jī)

return 0;

}

在上面這個(gè)函數(shù)中,第一行的格式不能改變,其中的h、m、s是三個(gè)全局變量,存儲(chǔ)的是設(shè)定的時(shí)間(時(shí)、分、秒)值。通過循環(huán)判斷,如果當(dāng)前時(shí)間滿足設(shè)定的條件,則調(diào)用MFC的函數(shù)ExitWindowsEx(UNIT uFlags, DWORD dwReserved)來關(guān)閉計(jì)算機(jī)。

2.線程的調(diào)用

線程的調(diào)用方式為:CWinThread * pThread=AfxBeginThread(ProcName,param,Priority),其中pThread是指向該線程的指針。源代碼及說明如下:

void CShutDlg::Onqd()

//設(shè)置時(shí)間后的響應(yīng)函數(shù)

{

UpdateData(TRUE); //從對(duì)話框取值

h=m_xsh; //把時(shí)、分、秒值傳給全局變量

m=m_fzh;

s=m_miao;

if (flag==1) {pThread->ResumeThread();}

//通過狀態(tài)標(biāo)志判斷,如果線程已經(jīng)啟動(dòng),則恢復(fù)運(yùn)行

else {

pThread=AfxBeginThread(timeThreadProc,GetSafeHwnd(),THREAD_PRIORITY_NORMAL); //如果線程沒運(yùn)行,則啟動(dòng)線程

flag=1;} //把線程狀態(tài)標(biāo)志位置1

m_chsh.EnableWindow(1);

//重設(shè)按鈕可用

m_qd.EnableWindow(0);

//設(shè)定按鈕不可用

}

點(diǎn)擊“重設(shè)”按鈕的響應(yīng)函數(shù):

void CShutDlg::Onchsh()

{

if(flag==1) //判斷標(biāo)志位

{

pThread->SuspendThread();

//如果線程已經(jīng)啟動(dòng),則掛起

}

m_chsh.EnableWindow(0);

//重設(shè)按鈕不可用

m_qd.EnableWindow(1); //設(shè)定按鈕可用

}

在啟動(dòng)線程的時(shí)候,用*pThread保存線程的指針使得我們可以對(duì)線程進(jìn)行掛起(SuspendThread函數(shù))、恢復(fù)(ResumeThread函數(shù))等操作,并通過全局變量h、m、s與線程通信,達(dá)到定時(shí)關(guān)機(jī)的目的。

3.動(dòng)態(tài)時(shí)鐘線程的實(shí)現(xiàn)

為了方便定時(shí),在此程序中加入了一個(gè)時(shí)鐘。原理主要是通過一個(gè)定時(shí)器(Timer),定時(shí)讀取當(dāng)前時(shí)間并按照格式顯示,這里涉及到了VC中的另一個(gè)重要函數(shù):OnTimer(UINT nIDEvent)。在程序啟動(dòng)初始化的時(shí)候,加入語句: m_nTimer=SetTimer(1,100,NULL),其中參數(shù)100是響應(yīng)周期(ms)。通過向?qū)Ъ尤霑r(shí)間響應(yīng)函數(shù),代碼如下:

void CShutDlg::OnTimer(UINT nIDEvent) //定時(shí)器響應(yīng)函數(shù)

{

CTime gg; //定義時(shí)間變量

CString s;

gg=CTime::GetCurrentTime();

//取出當(dāng)前時(shí)間

s.Format(“%02d”,gg.GetSecond());

//定義輸出格式

SetDlgItemText(IDC_miao1,s);

//在程序中顯示時(shí)間

s.Format(“%02d”,gg.GetHour());

SetDlgItemText(IDC_xsh1,s);

s.Format(“%02d”,gg.GetMinute());

SetDlgItemText(IDC_fzh1,s);

CDialog::OnTimer(nIDEvent);

}

OnTimer(UINT nIDEvent)是系統(tǒng)函數(shù),它參考初始化時(shí)設(shè)置的響應(yīng)周期(100ms)來執(zhí)行。需要注意的是,如果在程序中設(shè)置了Timer,那么在程序結(jié)束的時(shí)候要加上語句:KillTimer(0),以銷毀定時(shí)器對(duì)象,否則白白浪費(fèi)系統(tǒng)資源。

至此一個(gè)較為完整的定時(shí)器程序完成(其中重啟、注銷功能的實(shí)現(xiàn)很簡(jiǎn)單,也非本文的主題,故略過),如果再添加幾個(gè)線程,即可擴(kuò)展為一個(gè)多功能備忘錄,有興趣的讀者可以加以改進(jìn)。

小 結(jié)

本文中只是簡(jiǎn)單地運(yùn)用了一個(gè)線程,控制方式也是簡(jiǎn)單地與全局變量通信的方法,在實(shí)際應(yīng)用中還要注意線程同步、線程之間通信、線程與進(jìn)程之間通信、利用全局變量通信、利用用戶定義消息通信、利用事件通信等等許多重要問題。只有真正掌握了多線程高級(jí)編程技術(shù)才能寫出實(shí)用、優(yōu)秀的程序。