国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Windows下多線程編程技術及其實現

2019-11-18 12:20:39
字體:
來源:轉載
供稿:網友

  本文首先討論16位Windows下不具備的線程的概念,然后著重講述在32位Windows 95環境下多線程的編程技術
  ,最后給出利用該技術的一個實例,即基于Windows95下TCP/ip的可視電話的實現。
    要害詞:16位Windows環境,32位Windows95環境,進程,線程,TCP/IP,可視電話
  
    目錄
    1 問題的提出
    2 線程的概念
    3 線程的編程技術
    4 多線程編程技術的應用
    5 程序源碼
  
  一、問題的提出
    作者最近在開發基于Internet網上的可視電話過程中,碰到了這樣一個問題。在基于Internet網上的可視電話
  系統中,同時要進行語音采集、語音編解碼、圖象采集、圖象編解碼、語音和圖象 碼流的傳輸, 所有的這些事情
  ,都要并行處理。非凡是語音信號,假如進行圖象編解碼時間過長,語音信號得不到服務,通話就有間斷,假如圖
  象或語音處理時間過長,而不能及時的傳輸碼流數據,通信同樣也會中斷。這樣就要求我們實現一種并行編程,在
  只有一個CPU的機器上,也就是要將該CPU時間按照一定的優先準則分配給各個事件,定期處理某一事件而不會在某
  一事件處理過長,在32位Windows95或WindowsNT下,我們可以用多線程的編程技術來實現這種并行編程。實際上,
  這種并行編程在很多場合下都是必須的。例如,在FileManager拷貝文件時,它顯示一個對話框, 列出源文件和目
  標文件的名稱,并在對話框中包含了一個Cancel按鈕。假如在文件拷貝過程中,點中Cancel按鈕,就會終止拷貝。
  在16位Windows中,實現這類功能需要在FileCopy循環內部周期性地調用PeekMessage函數。假如正在讀一個很大的
  數據塊,則只有當這個塊讀完以后才能響應這個按鈕動作,假如從軟盤讀文件,則要花費好幾秒的時間,由于機器
  反應太遲鈍,你會頻繁地點中這個按鈕,以為系統不知道你想終止這個操作。假如把FileCopy指令放入另外一個線
  程,你就不需要在代碼中放一大堆PeekMessage函數,處理 用戶界面的線程將與它分開操作,這樣,點中Cancel按
  鈕后會立即得到響應。同樣的道理,在應用程序中創建一個單獨線程來處理所有打印任務也是很有用的,這樣,用
  戶可以在打印處理時繼續使用應用程序。
  
  二、線程的概念
    為了了解線程的概念,我們必須先討論一下進程的概念。
    一個進程通常定義為程序的一個實例。在Win32中, 進程占據4GB的地址空間。與它們在MS-DOS和16位Windows
  操作系統中不同, Win32進程是沒有活力的。這就是說,一個Win32進程并不執行什么指令,它只是占據著4GB的地
  址空間,此空間中有應用程序EXE文件的 代碼和數據。EXE需要的任意DLL也將它們的代碼和數據裝入到進程的地址
  空間。除了地址空間,進程還占有某些資源,比如文件、動態內存分配和線程。當進程終止時,在它生命期中創建
  的各種資源將被清除。
    但是進程是沒有活力的,它只是一個靜態的概念。為了讓進程完成一些工作,進程必須至少占有一個線程,所
  以線程是描述進程內的執行,正是線程負責執行包含在進程的地址空間中的代碼。實際上,單個進程可以包含幾個
  線程, 它們可以同時執行進程的地址空間中的代碼。為了做到這一點,每個線程有自己的一組CPU寄存器和堆棧。
  每個進程至少有一個線程在執行其地址空間中的代碼,假如沒有線程執行進程 地址空間中的代碼, 進程也就沒有
  繼續存在的理由,系統將自動清除進程及其地址空間。為了運行所有這些線程,操作系統為每個獨立線程安排一些
  CPU 時間,操作系統以輪轉方式向線程提供時間片,這就給人一種假象,好象這些線程都在同時運行。創建一個Wi
  n32進程時,它的第一個線程稱為主線程,它 由系統自動生成,然后可由這個主線程生成額外的線程,這些線程,
  又可生成更多的線程。
  
  三、線程的編程技術
    1、編寫線程函數
    所有線程必須從一個指定的函 數開始執行,該函數稱為線程函數,它必須具有下列原型:
      DWordWINAPIYourThreadFunc(LPVOIDlpvThreadParm);
    該函數輸入一個LPVOID型的參數,可以是一個DWORD型的整數,也可以是一個指向一個緩沖區的指針, 返回一
  個DWORD型的值。象WinMain函數一樣,這個函數并不由操作系統調用, 操作系統調用包含在KERNEL32.DLL中的非C
  運行時的一個內部函數,如StartOfThread,然后由StartOfThread函數建立起一個異常處理框架后,調用我們的函
  數。
    2、創建一個線程
    一個進程的主線程是由操作系統自動生成,假如你要讓一個主線程創建額外的線程,你可以調用來CreateThre
  ad完成。
    HANDLECreateThread(LPSECURITY_ATTRIBUTES lpsa,DWORDcbstack,LPTHREAD_START_ROUTINElpStartAddr,
              LPVOID lpvThreadParm,DWORDfdwCreate,LPDWORDlpIDThread);
    其中lpsa參數為一個指向SECURITY_ATTRIBUTES結構的指針。假如想讓對象為缺省安全屬性的話,可以傳一個N
  ULL,假如想讓任一個子進程都可繼續一個該線程對象句柄,必須指定一個SECURITY_ATTRIBUTES結構,其中bInher
  itHandle成員初始化為TRUE。參數cbstack表示線程為自己所用堆棧分配的地址空間大小,0表示采用系統缺省值。
  參數lpStartAddr用來表示新線程開始執行時代碼所在函數的地址,即為線程函數。lpvThreadParm為傳入線程函數
  的參數,fdwCreate參數指定控制線程創建的附加標志,可以取兩種值。假如該參數為0,線程就會立即開始執行,
  假如該參數為CREATE_SUSPENDED,則系統產生線程后,初始化CPU,登記CONTEXT結構的成員,預備好執行該線程函
  數中的第一條指令,但并不馬上執行,而是掛起該線程。最后一個參數lpIDThread 是一個DWORD類型地址,返回賦
  給該新線程的ID值。
    3、終止線程
    假如某線程調用了ExitThread 函數,就可以終止自己。
    VOIDExitThread(UINTfuExitCode );
    這個函數為調用該函數的線程設置了退出碼fuExitCode后, 就終止該線程。調用TerminateThread函數亦可終
  止線程。
    BOOLTerminateThread(HANDLE hThread,DWORDdwExitCode);
    該函數用來結束由hThread參數指定的線程, 并把dwExitCode設成該線程的退出碼。當某個線程不在響應時,
  我們可以用其他線程調用該函數來終止這個不響應的線程。
    4、設定線程的相對優先級
    當一個線程被首次創建時,它的優先級等同于它所屬進程的優先級。在單個進程內可以通過調用SetThreadPRi
  ority函數改變線程的相對優先級。一個線程的優先級是相對于其所屬的進程的優先級而言的。
    BOOLSetThreadPriority(HANDLE hThread,intnPriority);
    其中參數hThread是指向待修改 優先級線程的句柄,nPriority可以是以下的值:
    THREAD_PRIORITY_LOWEST,
    THREAD_PRIORITY_BELOW_NORMAL,
    THREAD_PRIORITY_NORMAL,
    THREAD_PRIORITY_ABOVE_NORMAL,
    THREAD_PRIORITY_HIGHEST
    5、掛起及恢復線程
    先前我提到過可以創建掛起狀態的線程(通過傳遞CREATE_SUSPENDED標志給函數CreateThread來實現)。當你
  這樣做時,系統創建指定線程的核心對象,創建線程的棧,在CONTEXT結構中初始化線程CPU注冊成員。然而,線程
  對象被分配了一個初始掛起計數值1,這表明了系統將不再分配CPU去執行線程。要開始執行一個線程,另一個線程
  必須調用ResumeThread并傳遞給它調用CreateThread時返回的線程句柄。
    DWORD ResumeThread(HANDLEhThread);
    一個線程可以被掛起多次。假如一個線程被掛起3次, 則該線程在它被分配CPU之前必須被恢復3次。除了在創
  建線程時使用CREATE_SUSPENDED標志,你還可以用SuspendThread函數掛起線程。
    DWORDSuspendThread(HANDLE hThread);
  
  四、多線程編程技術的應用
    我在前面說過,為了實現基于TCP/IP下的可視電話,就必須“并行”地執行語音采集、語音編解碼、圖象采集
  、圖象編解碼以及碼流數據的接收與發送。語音與圖象的采集由硬件采集卡進行,我們的程序只需初始化該硬件采
  集卡,然后實時讀取采集數據即可,但語音和圖象數據的編解碼以及碼流數據的傳輸都必須由程序去協調執行,決
  不能在某一件事件上處理過長,必須讓CPU輪流的為各個事件服務,Windows95下的線程正是滿足這種要求的編程技
  術。
    下面我給出了利用Windows95 環境下的多線程編程技術實現的基于TCP/IP的可視電話的部分源碼,其中包括主
  窗口過程函數,以及主叫端與被叫端的TCP/IP接收線程函數和語音編解碼的線程函數。由于圖象編解碼的實時性比
  語音處理與傳輸模塊的實時性的 要求要低些,所以我以語音編解碼為事件去查詢圖象數據,然后進行圖象編解碼,
  而沒有為圖象編解碼去單獨實現一個線程。
    在主窗口初始化時, 我用CREATE_SUSPENDED標志創建了兩個線程hThreadG7231和hThreadTCPRev。一個用于語
  音編解碼,它的線程函數為G723Proc, 該線程不斷查詢本地有無編好碼的語音和圖象的碼流,如有,則進行H.223
  打包,然后通過TCP的端口發送給對方。另外一個線程用于TCP/IP的接收,它的線程函數為AcceptThreadProcRev,
  該線程不斷偵 測TCP/IP端口有無對方傳來的碼流,如有,就接收碼流,進行H.223解碼后送入相應的緩沖區。該緩
  沖區的內容,由語音編解碼線程G72

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 梧州市| 翁源县| 乐安县| 阜平县| 微山县| 龙泉市| 南乐县| 乐都县| 甘德县| 南昌市| 渭源县| 洮南市| 兴文县| 安顺市| 壤塘县| 青神县| 清苑县| 北京市| 潼关县| 体育| 博罗县| 静安区| 阿勒泰市| 营山县| 洞口县| 临海市| 阜康市| 肃北| 房产| 通辽市| 蚌埠市| 青州市| 章丘市| 渭源县| 兴业县| 桐柏县| 绥阳县| 丘北县| 涿鹿县| 宜兴市| 万安县|