《電子技術應用》
您所在的位置:首頁 > 嵌入式技術 > 業界動態 > 用Visual C++實現工控設備多線程控制程序

用Visual C++實現工控設備多線程控制程序

2009-03-24
作者:齊 文 王勇前 曹志剛

  摘? 要: 提出多線程工控程序中最適宜采用工作者線程和事件同步方式,并給出了一個通用的工控程序框架。

  關鍵詞: 多線程 同步 事件

?

  多線程技術的引入,不僅可以挖掘潛在的CPU空閑時間,而且還可以提高應用程序的反應速度,其優點在有多個任務需要完成、有巨大數據流量的程序中反映得尤為明顯。而隨著Visual C++的引入,其靈活的線程實現機制使得程序員從繁瑣的Windows編程中解脫出來。關于多線程基本機理和實現方法近年來有許多文章介紹,這里不再贅述。本文將側重于比較在工控程序中采用各種線程類型和同步方法的優劣,并給出一個實用的、有較廣適應性的程序主體框架。

1 各種線程類型和同步方法

1.1 線程類型

  Visual C++中線程分為工作者線程(Worker Thread)和用戶界面線程(User Interface Thread)兩大類。

  用戶界面線程的特點是擁有單獨的消息隊列,可以具有自己的窗口界面,能夠對事件和用戶輸入做出響應,具體實現時由CWinThread派生出一個類。但其缺點是當需要停止或撤銷當前正在運行的線程而向其發送中止消息后,只有在消息隊列中排在前面的消息被一一處理完之后,線程才能接受中止消息并停止當前工作,這對CPU是一種浪費,在對實時性要求較高的工控程序中是不可容忍的。

  工作者線程適用于處理后臺任務,而不影響用戶對應用程序的使用。工作者線程僅僅由一個函數體實現,其實現簡單,便于編程者控制,與事件同步方法相配合能對中止消息做出較快反應。

1.2 同步方法

  在多線程應用程序中,兩個或更多的線程同時訪問相同數據會導致不可預知的結果,因此保持線程間的同步是一個不可或缺的環節。Visual C++提供了四種同步方法:臨界區(Critical Section)、信號燈(Semaphore)、互斥量(Mutex)和事件(Event)。

其中采用臨界區、信號燈或互斥量進行同步時,線程間的同步過程由操作系統完全控制,系統僅僅防止多個線程對同一資源的同時使用,而相同優先級的線程對同一資源的使用順序是編程者無法控制的。而在一般工控系統中,當主控臺下方設備數據變化時,應能及時中止當前的計算(如果當前計算未完成的話)并根據新的數據開始新一輪的計算,因而要求各線程對所處理的數據有一定的操作次序。

  事件同步是通過將事件自身設置為有信號或無信號來通知其它線程某一操作已完成或尚未完成,其設置可由編程人員手工完成,適合于工控程序應用。盡管事件同步方式平均效率比上面三種方式稍低,但在工控程序應用中相對于因數據未能及時更新而導致大量的無用計算及其對實時性的損害來講,還是非常值得的。

  下面介紹的是筆者參與某‘九五’預研項目中所設計的主控臺程序的基本框架,這個程序框架應能適用于大多數工控系統的主控程序。

2 軟件框架

  一般工控系統的主控部分通常所必須完成的兩件事是:(1)通過通信端口與下端設備通信,接收下端設備傳來的數據或向下端設備發送指令;(2)對下端設備所傳數據進行處理。

  與之相對應,該軟件具有一個主線程和兩個子線程,其中一個子線程為通信線程,另一個為計算線程。主線程是Windows下每個應用程序都具備的,負責線程間的同步、向計算線程和通信線程傳遞參數、管理人機界面、接收用戶輸入、數據庫的操作和管理等功能。通信線程通過通信端口(可以是串口、并口或網絡接口等)負責與下端的設備進行通信并交換數據,當存在多級控制結構時,還可用來與更高一級的控制設備進行通信并向上傳遞數據。計算線程負責核心算法的實現,根據系統的不同完成不同的數據處理任務。程序結構如圖1。

?

  進程開始后先由主線程建立通信線程與計算線程。通信線程監視通信端口,當下方設備發來數據時,就向主線程發送自定義的WM_USER_COMM_NOTIFY消息,通知主線程計算數據有所改變,主線程則對之進行處理,即中止當前的計算,并重新開始計算。

3 具體實現

  用Visual C++的AppWizard生成一個應用程序,這是主控程序的雛形,該應用程序暫取名為CtrSys,后面程序名都以此為準。

3.1 多線程的定義及生成

3.1.1 多線程的定義

  向項目中加入threads.cpp文件,在該文件中寫入通信線程和計算線程的控制函數

控制函數有下面的原型:

  UINT MyThreadProc(LPVOID lpvThreadParam);

  lpvThreadParam參數是32位的值,這個值就是在線程對象產生時傳遞給線程構造函數的參數。控制函數能解釋此值的不同表現方式。它可以被當作一個普通變量對待,也可以被視為一個指向包含有多個參數的結構指針,也可以被忽略。如果參數指向一個結構,這個結構可能不僅僅用來從調用者傳遞參數給線程,還可能用來從線程回傳數據給調用者。如果使用這樣的結構回傳給調用者,結果準備好后線程需要通知調用者。

  控制函數終止時,應該返回一個UINT類型的值,表明終止的原因。返回碼0表示成功,其它值表示不同類型的錯誤,這完全依賴實現情況。

  按一般程序示例,線程通常在視類或框架窗口類中產生。但在工控程序中,通信與計算線程常常要大量地對計算數據進行操作,根據文檔/視的程序框架結構,文檔類常常用來存儲所要處理的數據。因此把計算與通信線程放在文檔類中產生,并把產生線程的當前文檔對象的指針作為線程控制函數的參數傳遞給線程。

  從而,在控制函數(CalcThreadProc ()和CommThreadProc())一開始,就要對所傳來的參數進行識別:

  CCtrsysDoc* pDoc = (CCtrsysDoc*)pParam;

  注意要在文件開頭包括進文檔類的頭文件

  #include ″CtrsysDoc.h″

3.1.2? 多線程的產生

  在文檔類的構造函數中產生線程。程序啟動時生成文檔對象,同時啟動兩個線程。

??? ////////////////////////////////////

??? // CCtrsysDoc construction/destruction

CCtrsysDoc::CCtrsysDoc()

{

????……

??? m_pCalcThread=AfxBeginThread(CalcThreadProc, this);

??? m_pCommThread=AfxBeginThread(CommThreadProc, this);

}

??? 注意不要用Win32的CreateThread()建立線程,而應該用AfxBeginThread()函數,否則所建立的線程不能訪問其它MFC對象。

3.2 線程間的同步

??? 程序中設置有八個事件用于線程同步:

??? HANDLE m_hEventPost;???????????? //用來允許通信線程向主框架?

??? 發送WM_USER_COMM_NOTIFY消息

??? HANDLE m_hEventStartCalc;?????? ?//主框架通知計算線程開始計算

??? HANDLE m_hEventCalcStarted;????? //計算線程通知主框架計算已經開始

??? HANDLE m_hEventStopCalc;???????? //主框架通知計算線程中止計算

??? HANDLE m_hEventCalcStopped;????? //計算線程通知主框架計算已經中止

??? HANDLE m_hEventCalcDone;???????? //計算線程通知主框架計算已經結束

??? HANDLE m_hEventUpdateSourceData; //主框架通知計算線程更新數據

??? HANDLE m_hEventSourceDataUpdated; //通信線程通知主框架數據已更新完畢

??? 這八個事件是主線程和兩個子線程之間同步所必需的,讀者可根據自己程序的需要另行添加。

因各線程都以文檔對象指針為參數,這些事件都在文檔類頭文件中定義,這些事件在文檔類的構造函數中生成并賦初值。

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);

??? ……

}

??? 線程的同步工作主要在主框架CMainFrame類的WM_USER_COMM_NOTIFY消息響應函數OnCommNotify中進行。當下方通信設備參數改變時,通信線程發送給CMainFrame類一個WM_USER_COMM_NOTIFY消息。CMainFrame類接收到消息后,在消息響應函數OnCommNotify中終止計算線程的當前計算,計算成功終止后由通信線程更新計算所需的數據源,待更新完畢后,重新開始計算。線程同步部分流程如圖2。

?

3.3 通信線程

??? 通信線程部分流程如圖3所示。

3.4 計算線程

??? 編程者應根據數據處理過程,在運算量較大或循環次數較多的地方設置對m_hEventStopCalc事件的查詢。當數據發生更新時,使用其它線程類型和同步方法往往必須等到數據處理部分結束,這樣整個一次數據處理都是無用計算;而采用上述方法,因數據更新所造成的無用計算僅僅是一步循環或幾行指令,相比而言,所導致的延時和CPU浪費是微不足道的。

計算線程部分流程如圖4所示。

?

參考文獻

1 王 齊.Windows 95中的串行通信.微電腦世界,1997;(3)

2 (美)Richard C. Leinecker著.陳冠民,王如亮等譯.?Visual C++ 5.0 開發技術內幕. 北京:機械工業出版社, 1999

?

本站內容除特別聲明的原創文章之外,轉載內容只為傳遞更多信息,并不代表本網站贊同其觀點。轉載的所有的文章、圖片、音/視頻文件等資料的版權歸版權所有權人所有。本站采用的非本站原創文章及圖片等內容無法一一聯系確認版權者。如涉及作品內容、版權和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當措施,避免給雙方造成不必要的經濟損失。聯系電話:010-82306118;郵箱:aet@chinaaet.com。
亚洲一区二区欧美_亚洲丝袜一区_99re亚洲国产精品_日韩亚洲一区二区
亚洲欧美精品伊人久久| 日韩视频―中文字幕| 亚洲激情网址| 在线观看欧美日韩国产| 国产日产亚洲精品| 国产精品视频精品视频| 国产精品久久久久久久久久妞妞 | 亚洲视频一区在线观看| 亚洲精品中文字幕女同| 亚洲精品一级| 亚洲精品婷婷| 日韩亚洲欧美一区| 亚洲视频免费观看| 亚洲视频在线播放| 亚洲欧美日韩在线观看a三区| 亚洲亚洲精品在线观看| 亚洲欧美在线高清| 欧美在线黄色| 亚洲韩日在线| 亚洲精品在线一区二区| 一本一道久久综合狠狠老精东影业| 日韩系列在线| 亚洲一区二区三区高清| 欧美一区二区三区日韩视频| 久久国产精品黑丝| 葵司免费一区二区三区四区五区| 免费在线亚洲| 欧美日本不卡视频| 国产精品久久久久久亚洲调教| 国产精品乱码久久久久久| 国产欧美二区| 国产资源精品在线观看| 亚洲高清色综合| 亚洲伦理网站| 亚洲在线免费视频| 久久成人精品无人区| 91久久夜色精品国产九色| 亚洲精品在线视频| 亚洲在线视频| 久久人91精品久久久久久不卡| 免费亚洲视频| 欧美午夜不卡在线观看免费| 国产欧美一区二区精品秋霞影院| 精品999网站| 亚洲精品国产欧美| 亚洲一本大道在线| 亚洲高清一区二| 中文在线资源观看视频网站免费不卡| 午夜国产精品影院在线观看| 麻豆精品网站| 国产精品久久久久av免费| 韩日在线一区| 日韩一区二区精品视频| 欧美一区二区三区免费看| 亚洲另类自拍| 久久精品国语| 欧美日本国产在线| 国产一区二区三区精品欧美日韩一区二区三区 | 亚洲男同1069视频| 亚洲国产精品尤物yw在线观看| 一区二区高清在线观看| 久久大逼视频| 欧美久久影院| 国模精品一区二区三区| 日韩一级大片| 亚洲国产精品毛片| 亚洲尤物在线| 欧美二区在线| 国产拍揄自揄精品视频麻豆| 91久久精品国产91久久性色tv| 亚洲永久视频| 99天天综合性| 久久综合中文色婷婷| 国产精品久久久久999| 亚洲电影av| 欧美中文字幕在线观看| 亚洲午夜激情网页| 欧美成人在线免费视频| 国产精品一区在线播放| 亚洲人成在线影院| 久久精品人人爽| 欧美一区二区三区的| 欧美日韩国产成人| 国内精品伊人久久久久av影院 | 性久久久久久久久久久久| 99国内精品久久| 久久一区精品| 国产亚洲精品一区二555| 99国产精品久久久久老师| 91久久久在线| 久久资源av| 国产自产v一区二区三区c| 亚洲自拍啪啪| 亚洲综合99| 欧美日韩在线一二三| 亚洲激情中文1区| 亚洲国产精品美女| 久久人体大胆视频| 国产一区999| 亚洲欧美日韩精品久久奇米色影视| 99在线|亚洲一区二区| 女女同性精品视频| 黄网站色欧美视频| 性xx色xx综合久久久xx| 欧美亚洲在线视频| 国产精品xvideos88| 日韩亚洲视频在线| 一本色道久久综合精品竹菊 | 国产午夜亚洲精品羞羞网站| 亚洲视频免费在线观看| 亚洲影院在线观看| 国产精品xxx在线观看www| 日韩午夜在线播放| 一本在线高清不卡dvd| 欧美连裤袜在线视频| 91久久精品久久国产性色也91| 亚洲国产精品久久精品怡红院| 久久中文久久字幕| 一区二区三区在线不卡| 亚洲高清自拍| 欧美va天堂| 91久久精品www人人做人人爽| 亚洲精品精选| 欧美激情综合五月色丁香小说| 亚洲精品123区| 一区二区高清视频| 国产精品爱啪在线线免费观看| 在线一区二区视频| 午夜精品www| 国产日韩一区二区| 久久精品一区二区三区中文字幕 | 亚洲精品日韩久久| 欧美日本在线观看| 一区二区三区精品久久久| 午夜精品久久久久久久白皮肤| 国产精品一级| 久久精品夜色噜噜亚洲a∨| 欧美多人爱爱视频网站| 99re66热这里只有精品4| 午夜精品福利视频| 国产一区二区丝袜高跟鞋图片 | 国产一区二区av| 亚洲黄色性网站| 欧美日韩国产三级| 亚洲一区在线看| 久久久亚洲午夜电影| 在线成人av| 一本一本久久a久久精品综合麻豆| 欧美性视频网站| 欧美亚洲日本国产| 欧美韩日亚洲| 中日韩美女免费视频网址在线观看| 午夜欧美精品久久久久久久| 国精产品99永久一区一区| 日韩视频免费观看高清完整版| 国产精品盗摄久久久| 欧美一区午夜视频在线观看| 久久视频在线看| 亚洲精品国产精品乱码不99| 午夜一区二区三区在线观看| 一区二区三区在线高清| 亚洲一区二区日本| 国外成人在线视频网站| 一区二区日韩欧美| 国产一区二区中文字幕免费看| 亚洲精品一区二区网址| 国产精品系列在线| 最新精品在线| 国产精品一区二区久久久久| 亚洲电影在线看| 欧美午夜一区二区| 亚洲高清不卡一区| 国产精品va在线| 亚洲黄色在线| 国产精品欧美在线| 亚洲三级影片| 国产日韩欧美精品综合| 日韩视频在线观看免费| 国产欧美日韩精品在线| 亚洲精品国精品久久99热一| 国产欧美91| 亚洲一级一区| 在线视频国产日韩| 欧美一级大片在线观看| 亚洲日本一区二区| 久久精品视频一| 在线一区二区三区四区| 欧美成人四级电影| 午夜视频一区在线观看| 欧美日韩视频在线第一区| 亚洲国产高清在线| 国产欧美精品国产国产专区| aa级大片欧美| 在线播放中文字幕一区| 欧美伊人久久| 一区二区三区免费观看| 欧美777四色影视在线| 欧美亚洲三级| 国产精品欧美一区二区三区奶水 | 欧美一区二区三区免费观看视频|