用Visual C++實(shí)現工控設備多線(xiàn)程控制程序

發(fā)布時(shí)間:2009-3-25 16:45    發(fā)布者:李寬
關(guān)鍵詞: Visual , 工控 , 設備 , 線(xiàn)程
多線(xiàn)程技術(shù)的引入,不僅可以挖掘潛在的CPU空閑時(shí)間,而且還可以提高應用程序的反應速度,其優(yōu)點(diǎn)在有多個(gè)任務(wù)需要完成、有巨大數據流量的程序中反映得尤為明顯。而隨著(zhù)VisualC++的引入,其靈活的線(xiàn)程實(shí)現機制使得程序員從繁瑣的Windows編程中解脫出來(lái)。關(guān)于多線(xiàn)程基本機理和實(shí)現方法近年來(lái)有許多文章介紹,這里不再贅述。本文將側重于比較在工控程序中采用各種線(xiàn)程類(lèi)型和同步方法的優(yōu)劣,并給出一個(gè)實(shí)用的、有較廣適應性的程序主體框架。1 各種線(xiàn)程類(lèi)型和同步方法
1.1 線(xiàn)程類(lèi)型
Visual C++中線(xiàn)程分為工作者線(xiàn)程(Worker Thread)和用戶(hù)界面線(xiàn)程(User Interface Thread)兩大類(lèi)。
用戶(hù)界面線(xiàn)程的特點(diǎn)是擁有單獨的消息隊列,可以具有自己的窗口界面,能夠對事件和用戶(hù)輸入做出響應,具體實(shí)現時(shí)由CWinThread派生出一個(gè)類(lèi)。但其缺點(diǎn)是當需要停止或撤銷(xiāo)當前正在運行的線(xiàn)程而向其發(fā)送中止消息后,只有在消息隊列中排在前面的消息被一一處理完之后,線(xiàn)程才能接受中止消息并停止當前工作,這對CPU是一種浪費,在對實(shí)時(shí)性要求較高的工控程序中是不可容忍的。
工作者線(xiàn)程適用于處理后臺任務(wù),而不影響用戶(hù)對應用程序的使用。工作者線(xiàn)程僅僅由一個(gè)函數體實(shí)現,其實(shí)現簡(jiǎn)單,便于編程者控制,與事件同步方法相配合能對中止消息做出較快反應。
1.2 同步方法
在多線(xiàn)程應用程序中,兩個(gè)或更多的線(xiàn)程同時(shí)訪(fǎng)問(wèn)相同數據會(huì )導致不可預知的結果,因此保持線(xiàn)程間的同步是一個(gè)不可或缺的環(huán)節。VisualC++提供了四種同步方法:臨界區(Critical Section)、信號燈(Semaphore)、互斥量(Mutex)和事件(Event)。
其中采用臨界區、信號燈或互斥量進(jìn)行同步時(shí),線(xiàn)程間的同步過(guò)程由操作系統完全控制,系統僅僅防止多個(gè)線(xiàn)程對同一資源的同時(shí)使用,而相同優(yōu)先級的線(xiàn)程對同一資源的使用順序是編程者無(wú)法控制的。而在一般工控系統中,當主控臺下方設備數據變化時(shí),應能及時(shí)中止當前的計算(如果當前計算未完成的話(huà))并根據新的數據開(kāi)始新一輪的計算,因而要求各線(xiàn)程對所處理的數據有一定的操作次序。
事件同步是通過(guò)將事件自身設置為有信號或無(wú)信號來(lái)通知其它線(xiàn)程某一操作已完成或尚未完成,其設置可由編程人員手工完成,適合于工控程序應用。盡管事件同步方式平均效率比上面三種方式稍低,但在工控程序應用中相對于因數據未能及時(shí)更新而導致大量的無(wú)用計算及其對實(shí)時(shí)性的損害來(lái)講,還是非常值得的。
下面介紹的是筆者參與某‘九五’預研項目中所設計的主控臺程序的基本框架,這個(gè)程序框架應能適用于大多數工控系統的主控程序。
2 軟件框架
一般工控系統的主控部分通常所必須完成的兩件事是1)通過(guò)通信端口與下端設備通信,接收下端設備傳來(lái)的數據或向下端設備發(fā)送指令;(2)對下端設備所傳數據進(jìn)行處理。
與之相對應,該軟件具有一個(gè)主線(xiàn)程和兩個(gè)子線(xiàn)程,其中一個(gè)子線(xiàn)程為通信線(xiàn)程,另一個(gè)為計算線(xiàn)程。主線(xiàn)程是Windows下每個(gè)應用程序都具備的,負責線(xiàn)程間的同步、向計算線(xiàn)程和通信線(xiàn)程傳遞參數、管理人機界面、接收用戶(hù)輸入、數據庫的操作和管理等功能。通信線(xiàn)程通過(guò)通信端口(可以是串口、并口或網(wǎng)絡(luò )接口等)負責與下端的設備進(jìn)行通信并交換數據,當存在多級控制結構時(shí),還可用來(lái)與更高一級的控制設備進(jìn)行通信并向上傳遞數據。計算線(xiàn)程負責核心算法的實(shí)現,根據系統的不同完成不同的數據處理任務(wù)。程序結構如圖1。

進(jìn)程開(kāi)始后先由主線(xiàn)程建立通信線(xiàn)程與計算線(xiàn)程。通信線(xiàn)程監視通信端口,當下方設備發(fā)來(lái)數據時(shí),就向主線(xiàn)程發(fā)送自定義的WM_USER_COMM_NOTIFY消息,通知主線(xiàn)程計算數據有所改變,主線(xiàn)程則對之進(jìn)行處理,即中止當前的計算,并重新開(kāi)始計算。
3 具體實(shí)現
用Visual C++的AppWizard生成一個(gè)應用程序,這是主控程序的雛形,該應用程序暫取名為CtrSys,后面程序名都以此為準。
3.1 多線(xiàn)程的定義及生成
3.1.1 多線(xiàn)程的定義
向項目中加入threads.cpp文件,在該文件中寫(xiě)入通信線(xiàn)程和計算線(xiàn)程的控制函數。
控制函數有下面的原型:
  UINT MyThreadProc(LPVOID lpvThreadParam);
lpvThreadParam參數是32位的值,這個(gè)值就是在線(xiàn)程對象產(chǎn)生時(shí)傳遞給線(xiàn)程構造函數的參數?刂坪瘮的芙忉尨酥档牟煌憩F方式。它可以被當作一個(gè)普通變量對待,也可以被視為一個(gè)指向包含有多個(gè)參數的結構指針,也可以被忽略。如果參數指向一個(gè)結構,這個(gè)結構可能不僅僅用來(lái)從調用者傳遞參數給線(xiàn)程,還可能用來(lái)從線(xiàn)程回傳數據給調用者。如果使用這樣的結構回傳給調用者,結果準備好后線(xiàn)程需要通知調用者。
控制函數終止時(shí),應該返回一個(gè)UINT類(lèi)型的值,表明終止的原因。返回碼0表示成功,其它值表示不同類(lèi)型的錯誤,這完全依賴(lài)實(shí)現情況。
按一般程序示例,線(xiàn)程通常在視類(lèi)或框架窗口類(lèi)中產(chǎn)生。但在工控程序中,通信與計算線(xiàn)程常常要大量地對計算數據進(jìn)行操作,根據文檔/視的程序框架結構,文檔類(lèi)常常用來(lái)存儲所要處理的數據。因此把計算與通信線(xiàn)程放在文檔類(lèi)中產(chǎn)生,并把產(chǎn)生線(xiàn)程的當前文檔對象的指針作為線(xiàn)程控制函數的參數傳遞給線(xiàn)程。
從而,在控制函數(CalcThreadProc ()和CommThreadProc())一開(kāi)始,就要對所傳來(lái)的參數進(jìn)行識別:
  CCtrsysDoc* pDoc = (CCtrsysDoc*)pParam;
注意要在文件開(kāi)頭包括進(jìn)文檔類(lèi)的頭文件
  #include ″CtrsysDoc.h″
3.1.2  多線(xiàn)程的產(chǎn)生
  在文檔類(lèi)的構造函數中產(chǎn)生線(xiàn)程。程序啟動(dòng)時(shí)生成文檔對象,同時(shí)啟動(dòng)兩個(gè)線(xiàn)程。
    ////////////////////////////////////
    // CCtrsysDoc construction/destruction
CCtrsysDoc::CCtrsysDoc()
{
    ……
    m_pCalcThread=AfxBeginThread(CalcThreadProc, this);
    m_pCommThread=AfxBeginThread(CommThreadProc, this);
}
    注意不要用Win32的CreateThread()建立線(xiàn)程,而應該用AfxBeginThread()函數,否則所建立的線(xiàn)程不能訪(fǎng)問(wèn)其它MFC對象。
3.2 線(xiàn)程間的同步
程序中設置有八個(gè)事件用于線(xiàn)程同步:
    HANDLE m_hEventPost;             //用來(lái)允許通信線(xiàn)程向主框架  
    發(fā)送WM_USER_COMM_NOTIFY消息
    HANDLE m_hEventStartCalc;        //主框架通知計算線(xiàn)程開(kāi)始計算
    HANDLE m_hEventCalcStarted;      //計算線(xiàn)程通知主框架計算已經(jīng)開(kāi)始
    HANDLE m_hEventStopCalc;         //主框架通知計算線(xiàn)程中止計算
    HANDLE m_hEventCalcStopped;      //計算線(xiàn)程通知主框架計算已經(jīng)中止
    HANDLE m_hEventCalcDone;         //計算線(xiàn)程通知主框架計算已經(jīng)結束
    HANDLE m_hEventUpdateSourceData; //主框架通知計算線(xiàn)程更新數據
    HANDLE m_hEventSourceDataUpdated; //通信線(xiàn)程通知主框架數據已更新完畢
    這八個(gè)事件是主線(xiàn)程和兩個(gè)子線(xiàn)程之間同步所必需的,讀者可根據自己程序的需要另行添加。
因各線(xiàn)程都以文檔對象指針為參數,這些事件都在文檔類(lèi)頭文件中定義,這些事件在文檔類(lèi)的構造函數中生成并賦初值。
CCtrsysDoc::CCtrsysDoc()
{
    ……
    m_hEventPost=CreateEvent(NULL,TRUE,TRUE, NULL);
    m_hEventCalcDone=CreateEvent(NULL,TRUE,FALSE, NULL);
    m_hEventCalcStarted=CreateEvent(NULL,TRUE,FALSE,NULL);
    m_hEventStartCalc=CreateEvent(NULL, TRUE,FALSE, NULL);
    m_hEventSourceDataUpdated=CreateEvent(NULL,TRUE,FALSE, NULL);
    m_hEventUpdateSourceData=CreateEvent(NULL,TRUE,FALSE, NULL);
    m_hEventCalcStopped=CreateEvent(NULL,TRUE,FALSE, NULL);
    m_hEventStopCalc=CreateEvent(NULL, TRUE,FALSE, NULL);
    ……
}
線(xiàn)程的同步工作主要在主框架CMainFrame類(lèi)的WM_USER_COMM_NOTIFY消息響應函數OnCommNotify中進(jìn)行。當下方通信設備參數改變時(shí),通信線(xiàn)程發(fā)送給CMainFrame類(lèi)一個(gè)WM_USER_COMM_NOTIFY消息。CMainFrame類(lèi)接收到消息后,在消息響應函數OnCommNotify中終止計算線(xiàn)程的當前計算,計算成功終止后由通信線(xiàn)程更新計算所需的數據源,待更新完畢后,重新開(kāi)始計算。線(xiàn)程同步部分流程如圖2。

3.3 通信線(xiàn)程
通信線(xiàn)程部分流程如圖3所示。

3.4 計算線(xiàn)程
編程者應根據數據處理過(guò)程,在運算量較大或循環(huán)次數較多的地方設置對m_hEventStopCalc事件的查詢(xún)。當數據發(fā)生更新時(shí),使用其它線(xiàn)程類(lèi)型和同步方法往往必須等到數據處理部分結束,這樣整個(gè)一次數據處理都是無(wú)用計算;而采用上述方法,因數據更新所造成的無(wú)用計算僅僅是一步循環(huán)或幾行指令,相比而言,所導致的延時(shí)和CPU浪費是微不足道的。
計算線(xiàn)程部分流程如圖4所示。
本文地址:http://selenalain.com/thread-2586-1-1.html     【打印本頁(yè)】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀(guān)點(diǎn)和對其真實(shí)性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問(wèn)題,我們將根據著(zhù)作權人的要求,第一時(shí)間更正或刪除。
freeboy898 發(fā)表于 2011-11-4 14:48:17
大體的流程知道了,能再講詳細點(diǎn)就好了,學(xué)習了,謝謝樓主分享!
rewwen 發(fā)表于 2012-8-1 18:58:44
謝謝學(xué)習了。。。。。。
daizhi1970 發(fā)表于 2012-8-1 20:58:14
O(∩_∩)O謝謝
daizhi1970 發(fā)表于 2012-8-1 20:58:24
O(∩_∩)O謝謝
daizhi1970 發(fā)表于 2012-8-1 20:58:29
O(∩_∩)O謝謝
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表
午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页