小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

VC多線程編程學(xué)習(xí)筆記(一)

 云將東游 2014-07-08

VC多線程編程學(xué)習(xí)筆記(一)

    最近兩天在學(xué)多線程編程,有了一些心得,寫下來和大家一起共勉。文中一些部分引用了韓耀旭的文章《多線程編程》http://www./document/viewdoc/?id=1704和MSDN資料。

一、緣起

工作上要用到串口編程,本來一直是用mscomm控件來進(jìn)行串口通訊的,后來覺得這個(gè)控件功能不靈活,想直接使用api編程,那就不可避免的要使用多線程技術(shù):用一個(gè)支線程一直掛在那里監(jiān)聽串口,就不影響主線程的消息循環(huán)了。

 

二、為何要用多線程

有時(shí)候需要把程序的運(yùn)行掛起一段時(shí)間,我們會(huì)用到

Sleep(5000);

來讓程序掛起5秒鐘,而這個(gè)時(shí)候,程序在這5秒鐘里就“死”在那里了,不再響應(yīng)其他任何消息。

或者有時(shí)候會(huì)用一個(gè)

While(1)

這樣一個(gè)死循環(huán)去完成一些監(jiān)聽工作,但這樣的話,主界面也會(huì)“死”在那里。

這些也許都不是程序員的本意,那我們可以使用多線程技術(shù),把一些耗時(shí)的操作放到支線程里去,而不影響主線程的消息循環(huán)。

 

三、相關(guān)函數(shù)

1.     HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadID );

該函數(shù)在其調(diào)用進(jìn)程的進(jìn)程空間里創(chuàng)建一個(gè)新的線程,并返回已建線程的句柄,其中各參數(shù)說明如下:

  • lpThreadAttributes:指向一個(gè) SECURITY_ATTRIBUTES 結(jié)構(gòu)的指針,該結(jié)構(gòu)決定了線程的安全屬性,一般置為 NULL;
  • dwStackSize:指定了線程的堆棧深度,一般都設(shè)置為0;
  • lpStartAddress:表示新線程開始執(zhí)行時(shí)代碼所在函數(shù)的地址,即線程的起始地址。一般情況為(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc 是線程函數(shù)名;
  • lpParameter:指定了線程執(zhí)行時(shí)傳送給線程的32位參數(shù),即線程函數(shù)的參數(shù);
  • dwCreationFlags:控制線程創(chuàng)建的附加標(biāo)志,可以取兩種值。如果該參數(shù)為0,線程在被創(chuàng)建后就會(huì)立即開始執(zhí)行;如果該參數(shù)為CREATE_SUSPENDED,則系統(tǒng)產(chǎn)生線程后,該線程處于掛起狀態(tài),并不馬上執(zhí)行,直至函數(shù)ResumeThread被調(diào)用;
  • lpThreadId:該參數(shù)返回所創(chuàng)建線程的ID;

如果創(chuàng)建成功則返回線程的句柄,否則返回NULL。

2.     DWORD SuspendThread(HANDLE hThread);

該函數(shù)用于掛起指定的線程,如果函數(shù)執(zhí)行成功,則線程的執(zhí)行被終止。

3.     DWORD ResumeThread(HANDLE hThread);

該函數(shù)用于結(jié)束線程的掛起狀態(tài),執(zhí)行線程。

4.     VOID ExitThread(DWORD dwExitCode);

該函數(shù)用于線程終結(jié)自身的執(zhí)行,主要在線程的執(zhí)行函數(shù)中被調(diào)用。其中參數(shù)dwExitCode用來設(shè)置線程的退出碼。

5.     BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);

一般情況下,線程運(yùn)行結(jié)束之后,線程函數(shù)正常返回,但是應(yīng)用程序可以調(diào)用TerminateThread強(qiáng)行終止某一線程的執(zhí)行。各參數(shù)含義如下:

  • hThread:將被終結(jié)的線程的句柄;
  • dwExitCode:用于指定線程的退出碼。

  使用TerminateThread()終止某個(gè)線程的執(zhí)行是不安全的,可能會(huì)引起系統(tǒng)不穩(wěn)定;雖然該函數(shù)立即終止線程的執(zhí)行,但并不釋放線程所占用的資源。因此,一般不建議使用該函數(shù)。

6.     BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM lParam);

該函數(shù)將一條消息放入到指定線程的消息隊(duì)列中,并且不等到消息被該線程處理時(shí)便返回。

  • idThread:將接收消息的線程的ID;
  • Msg:指定用來發(fā)送的消息;
  • wParam:同消息有關(guān)的字參數(shù);
  • lParam:同消息有關(guān)的長(zhǎng)參數(shù);

調(diào)用該函數(shù)時(shí),如果即將接收消息的線程沒有創(chuàng)建消息循環(huán),則該函數(shù)執(zhí)行失敗。

7.     DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);

  • hHandle為要監(jiān)視的對(duì)象(一般為同步對(duì)象,也可以是線程)的句柄;
  • dwMilliseconds為hHandle對(duì)象所設(shè)置的超時(shí)值,單位為毫秒;(有兩個(gè)特殊值:0,則函數(shù)立即返回,若為INFINITE,則函數(shù)會(huì)一直掛起,直到hHandle所指向的對(duì)象變?yōu)橛行盘?hào)狀態(tài)。)

      四、兩個(gè)重要元素

        1. Volatile 
       volatile 修飾符的作用是告訴編譯器無需對(duì)該變量作任何的優(yōu)化,即無需將它放到一個(gè)寄存器中,并且該值可被外部改變。對(duì)于多線程引用的全局變量來說,volatile 是一個(gè)非常重要的修飾符。

       2. 死鎖
      多線程編程中,會(huì)出現(xiàn)多個(gè)線程都需要使用同一個(gè)資源,這時(shí),為了保證數(shù)據(jù)同步,我們可以使用很多種方法,在線程1使用某個(gè)資源的時(shí)候,鎖住它,而此時(shí),線程2也申請(qǐng)使用此資源時(shí),就只能等待,直到線程1釋放了這個(gè)資源,這是很重要的,但如果不注意,若線程1正在使用資源1,而線程2正在使用資源2,而雙方都申請(qǐng)了對(duì)方所鎖住的資源,則發(fā)生了死鎖,互相申請(qǐng)不到,結(jié)果兩個(gè)線程都“死”在了那里。

 

      五、一個(gè)簡(jiǎn)單的使用多線程技術(shù)的小對(duì)話框(使用mfc)

     在vc中新建一個(gè)對(duì)話框程序,布局如圖:

VC多線程編程學(xué)習(xí)筆記(一)

 

1.在對(duì)話框的.cpp文件中加入以下兩句:

#include "afxmt.h"    //為了使用事件對(duì)象CEvent ,所需的頭文件
CEvent event1;        //事件對(duì)象

 

2.加入兩個(gè)全局函數(shù)作為兩個(gè)支線程的入口函數(shù):

UINT proc1(LPARAM lParam)
{
 CEdit* pEdit = (CEdit*)lParam;
 CString str;
 int i=1;
 while (1)
 {
  str.Format("第%d次刷新",i);
  pEdit->SetWindowText(str);
  if (i%5==0)
  {
   event1.SetEvent();
  }
  i++;
  Sleep(1000);
 }
}

 

 

UINT proc2(LPARAM lParam)
{
 CEdit* pEdit = (CEdit*)lParam;
 CString str;
 CTime time;
 while (1)
 {
  WaitForSingleObject(event1.m_hObject,INFINITE);
  time = CTime::GetCurrentTime();
  str = time.Format("%H : %M : %S");
  pEdit->SetWindowText(str);
 }
}

 

3.為兩個(gè)只讀的文本框添加控件變量 m_edit1 ,m_edit2

4.為按鈕添加單擊事件函數(shù):

void CExampleMultiThreadDlg::OnStart()
{
 HANDLE thread1 = CreateThread(NULL,

                          0,

                          (LPTHREAD_START_ROUTINE)proc1,

                          &m_edit1,

                          0,

                          NULL);
 HANDLE thread2 = CreateThread(NULL,

                          0,

                          (LPTHREAD_START_ROUTINE)proc2,

                          &m_edit2,

                          0,

                          NULL);
}

5.運(yùn)行后,點(diǎn)擊開始按鈕,兩個(gè)分線程便開始工作了,線程1會(huì)每秒鐘刷新一次第一個(gè)對(duì)話框,每刷新5次,線程2就在第二個(gè)對(duì)話框中刷新一下當(dāng)前時(shí)間。

程序中用到的CEvent對(duì)象是個(gè)線程同步對(duì)象,用來在線程之間發(fā)送信息,我會(huì)在下面的學(xué)習(xí)筆記中闡述用法。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多