摘要:簡(jiǎn)要介紹Vega應(yīng)用程序的基本框架;重點(diǎn)分析基于MFC的Vega應(yīng)用程序的基本框架和開(kāi)發(fā)中所遇到的兩個(gè)線程問(wèn)題,并提供相應(yīng)的解決方法。 論文網(wǎng),期刊發(fā)表網(wǎng),職稱(chēng)論文發(fā)表
關(guān)鍵詞:仿真;MFC;線程;Vega
1Vega應(yīng)用程序基本框架
1.1Vega應(yīng)用程序開(kāi)發(fā)模式簡(jiǎn)介
Vega是一種用于實(shí)時(shí)仿真及虛擬現(xiàn)實(shí)應(yīng)用的高性能軟件環(huán)境和工具,主要包括兩個(gè)部分:一個(gè)是被稱(chēng)為L(zhǎng)ynX的圖形用戶(hù)界面的工具箱,另一個(gè)則是基于C語(yǔ)言的Vega函數(shù)庫(kù)。LynX的主要功能是通過(guò)可視化操作建立起三維場(chǎng)景模型,并將其保存在一個(gè)應(yīng)用定義文件(.ADF)中,而后應(yīng)用程序就可以通過(guò)調(diào)用Vega的C語(yǔ)言函數(shù)庫(kù)來(lái)對(duì)已建好的三維場(chǎng)景進(jìn)行渲染驅(qū)動(dòng)。
1.2Vega應(yīng)用程序基本框架分析
Vega編程類(lèi)似于C編程,包括完整的C語(yǔ)言應(yīng)用程序接口,為軟件開(kāi)發(fā)人員提供最大程度的軟件控制和靈活性。對(duì)于WindowsNT平臺(tái)上的Vega應(yīng)用,主要有三種類(lèi)型:控制臺(tái)程序、傳統(tǒng)的Windows應(yīng)用程序和基于MFC(MicrosoftFoundationClasses)的應(yīng)用。但無(wú)論是哪一種應(yīng)用,建立Vega應(yīng)用程序都需要以下三個(gè)步驟:
第一步,初始化Vega系統(tǒng)并創(chuàng)建共享內(nèi)存等;
第二步,通過(guò)ADF應(yīng)用定義文件加載三維模型或是通過(guò)顯式的函數(shù)調(diào)用來(lái)動(dòng)態(tài)加載三維模型;
第三步,通過(guò)調(diào)用配置函數(shù)設(shè)置完Vega系統(tǒng)后,就開(kāi)始了Vega應(yīng)用程序的主循環(huán),主循環(huán)的作用是對(duì)三維視景進(jìn)行渲染驅(qū)動(dòng)。它主要分兩步,即對(duì)于給定的幀速進(jìn)行幀同步和對(duì)當(dāng)前的顯示幀進(jìn)行必要的處理。
以下是一個(gè)最基本的Vega應(yīng)用程序框架:
main(){
vgInitSys();//初始化
vgDefineSys(“.adf”文件);//定義
vgConfigSys();//配置
while(1){
vgSyncFrame();//同步幀
vgFrame();//幀內(nèi)處理
//應(yīng)用程序特定代碼}
這是一個(gè)控制臺(tái)的應(yīng)用程序。但是Vega只是一個(gè)包含十幾種不同模塊的函數(shù)集,并沒(méi)有窗口函數(shù)(雖然Vega函數(shù)庫(kù)中提供了一些窗口和事件管理的函數(shù),但這些函數(shù)在實(shí)際應(yīng)用中還遠(yuǎn)遠(yuǎn)不夠),它缺乏面向?qū)ο竽芰,不符合?dāng)前流行的軟件設(shè)計(jì)思想,因此需要一個(gè)窗口系統(tǒng)來(lái)完成Vega實(shí)時(shí)仿真的程序設(shè)計(jì)。而如果在Windows平臺(tái)上開(kāi)發(fā),具有良好圖形用戶(hù)界面的應(yīng)用程序?qū)⒏艿綒g迎。對(duì)于基于窗口的應(yīng)用程序來(lái)說(shuō),Vega系統(tǒng)通過(guò)提供一個(gè)窗口初始化函數(shù)調(diào)用來(lái)完成,即只要把上述的初始化函數(shù)vgInitSys()替換成vgInitWinSys()即可。該函數(shù)通過(guò)獲得窗口句柄來(lái)初始化Vega的顯示窗口。Vega窗口和Windows窗口如圖1所示。
2MFC技術(shù)在Vega應(yīng)用程序設(shè)計(jì)中的應(yīng)用
2.1MFC技術(shù)與Vega應(yīng)用程序的接口分析
鑒于Vega函數(shù)是用C++語(yǔ)言編寫(xiě)以及在Windows平臺(tái)上進(jìn)行開(kāi)發(fā),所以就選擇了VisualC++這種Windows環(huán)境下最好的C++編譯器作為開(kāi)發(fā)工具。VisualC++中的MFC類(lèi)庫(kù)已是一個(gè)相當(dāng)成熟的類(lèi)庫(kù),特別是其基于文檔/視圖結(jié)構(gòu)的應(yīng)用程序框架,已成為開(kāi)發(fā)Windows應(yīng)用程序的主流框架結(jié)構(gòu)。該框架結(jié)構(gòu)能夠?qū)⒊绦蛑械臄?shù)據(jù)和顯示部分進(jìn)行有效的隔離,并能將一個(gè)文檔與多個(gè)視圖進(jìn)行對(duì)應(yīng)。
為便于開(kāi)發(fā)出基于MFC的Vega應(yīng)用程序,Vega通過(guò)繼承MFC中的CView類(lèi)而派生出一個(gè)子類(lèi)zsVegaView。這個(gè)zsVegaView類(lèi)提供了啟動(dòng)一個(gè)Vega線程最基本的功能,還以虛函數(shù)的形式定義了特定的應(yīng)用程序要進(jìn)行操作的通用接口,因此用戶(hù)的應(yīng)用程序只需從zsVegaView派生出新類(lèi)并根據(jù)需要重載必要的虛函數(shù)即可。從設(shè)計(jì)模式的觀點(diǎn)來(lái)看,它是采用了模板方法模式(TemplateMethod)。模板方法模式是一種類(lèi)行為模式,其意圖是定義一個(gè)操作算法的骨架,而將一些具體步驟延遲到子類(lèi)中去,這是代碼重用的一種基本技術(shù)。
2.2基于MFC的Vega應(yīng)用程序的線程分析
通過(guò)采用模板方法可以將開(kāi)發(fā)一個(gè)基于MFC應(yīng)用程序的工作量減少到最低,這是Vega系統(tǒng)提供的方法,但由于MFC類(lèi)庫(kù)并不是一個(gè)支持多線程訪問(wèn)的類(lèi)庫(kù),而派生的子類(lèi)是通過(guò)在OnInitialUpdate()函數(shù)中調(diào)用基類(lèi)的runVega()來(lái)啟動(dòng)Vega線程,并將派生類(lèi)的指針作為參數(shù)傳給新啟動(dòng)的子線程,這恰是問(wèn)題的所在。由于源代碼中的類(lèi)空間和線程運(yùn)行時(shí)的線程空間是可以相互交迭的,亦即不同的線程在運(yùn)行時(shí)可以訪問(wèn)相同的類(lèi)的實(shí)例(對(duì)象),而MFC類(lèi)庫(kù)本身設(shè)計(jì)時(shí)并未考慮到多線程訪問(wèn),因此在線程間傳遞視圖類(lèi)CView(其子類(lèi)對(duì)象也是一個(gè)CView對(duì)象)是不安全的。
2.2.1在Vega線程中更新視圖時(shí)訪問(wèn)保護(hù)異常錯(cuò)誤的分析
錯(cuò)誤分析:在單文檔多視圖中,在Vega線程中改變文檔數(shù)據(jù)后通過(guò)調(diào)用函數(shù)UpdateAllViews()來(lái)更新所有相應(yīng)的視圖時(shí)立即出現(xiàn)了訪問(wèn)保護(hù)異常的錯(cuò)誤。這是因?yàn)橛妙?lèi)CView的派生類(lèi)來(lái)嵌入與Vega功能有關(guān)的功能代碼對(duì)于CView的關(guān)聯(lián)只使用了CView類(lèi)的視圖窗口的句柄,這種設(shè)計(jì)違反了軟件設(shè)計(jì)的基本準(zhǔn)則:高內(nèi)聚,低耦合。
解決方法:為了既能保持由模板方法設(shè)計(jì)帶來(lái)的好處,又能達(dá)到高內(nèi)聚、低耦合的目標(biāo),最好的方法就是進(jìn)行切割分離,即將所有與Vega系統(tǒng)有關(guān)的數(shù)據(jù)和操作單獨(dú)作為一個(gè)基類(lèi)CVega來(lái)實(shí)現(xiàn),并保持用戶(hù)的擴(kuò)展接口,然后只需從CVega類(lèi)派生出新類(lèi)并將視圖窗口的句柄作為參數(shù)進(jìn)行傳遞。由于Windows平臺(tái)采用消息驅(qū)動(dòng)機(jī)制,所以當(dāng)Vega線程改變數(shù)據(jù)后可以利用視圖窗口的句柄發(fā)送消息來(lái)通知各個(gè)視圖窗口及時(shí)更新。
2.2.2切換三維場(chǎng)景時(shí)地址訪問(wèn)保護(hù)錯(cuò)誤的分析
錯(cuò)誤分析:Vega應(yīng)用程序一般通過(guò)應(yīng)用程序定義文件(.ADF)載入三維場(chǎng)景模型,而在實(shí)際開(kāi)發(fā)的過(guò)程中,當(dāng)打開(kāi)應(yīng)用程序時(shí)需要在不退出該應(yīng)用程序的前提下需要進(jìn)行三維場(chǎng)景切換,即載入新場(chǎng)景;但是,當(dāng)Vega線程未退出時(shí)重新載入場(chǎng)景會(huì)失敗,而在切換場(chǎng)景時(shí)讓正在運(yùn)行的線程自然終止而重新開(kāi)啟另一個(gè)線程則出現(xiàn)了一個(gè)地址訪問(wèn)保護(hù)的錯(cuò)誤。該錯(cuò)誤發(fā)生在Vega啟動(dòng)時(shí)的初始化系統(tǒng)函數(shù)vgInitWinSys()執(zhí)行的過(guò)程中,原因是引用了無(wú)效的指針。vgInitWinSys()函數(shù)的作用主要是初始化Vega系統(tǒng)并創(chuàng)建共享內(nèi)存等,同時(shí)在后臺(tái)開(kāi)啟了一個(gè)Vega窗口子線程,該子線程根據(jù)傳送的窗口句柄參數(shù)創(chuàng)建一個(gè)與該句柄對(duì)應(yīng)的Windows窗口相同大小的Vega窗口,并將它覆蓋在Windows窗口上,這樣Vega系統(tǒng)的渲染窗口就可以嵌入到基于MFC的視圖窗口上。該子線程的創(chuàng)建是必需的,但卻無(wú)法終止它,這是因?yàn)樗荲ega函數(shù)內(nèi)部創(chuàng)建的,而線程又隸屬于進(jìn)程,只有進(jìn)程結(jié)束了,所有的線程才全部退出。所以,即使創(chuàng)建它的父線程已“死”,它卻還“活”著,但因此而保留了一些無(wú)用的參數(shù)如無(wú)效的指針等。而且,當(dāng)?shù)诙䝼(gè)線程啟動(dòng)時(shí)函數(shù)vgInitWinSys()卻不再啟動(dòng)新的子線程而是繼續(xù)保留原來(lái)沒(méi)“死”的窗口線程,這就導(dǎo)致了地址訪問(wèn)保護(hù)的錯(cuò)誤。
解決方法:就是創(chuàng)建一個(gè)單獨(dú)的Vega進(jìn)程。其設(shè)計(jì)思想是通過(guò)將同一個(gè)應(yīng)用程序中的不同部分進(jìn)行相互黑箱化,彼此之間僅通過(guò)定義好的接口進(jìn)行訪問(wèn),這就最大限度地減小各部分之間的相互影響。Windows不是一個(gè)實(shí)時(shí)操作系統(tǒng),而是一個(gè)比較穩(wěn)定的系統(tǒng)。由于虛擬仿真系統(tǒng)一般都是實(shí)時(shí)的,在它的視景驅(qū)動(dòng)模塊中將處理大量的實(shí)時(shí)仿真結(jié)果數(shù)據(jù),所以必須保證該模塊中的兩個(gè)進(jìn)程之間能快速有效地進(jìn)行通信。
在WindowsNT平臺(tái)上,進(jìn)程間通信的主要方式有:動(dòng)態(tài)數(shù)據(jù)交換(DDE)、網(wǎng)絡(luò)動(dòng)態(tài)數(shù)據(jù)交換(NetDDE)、Windows套接字(WindowsSockets)、命名管道(NamedPipes)、內(nèi)存映射文件(Memory-MappedFiles)、NetBIOS、遠(yuǎn)程過(guò)程調(diào)用(RPC)以及磁盤(pán)文件等。在視景驅(qū)動(dòng)模塊中,由于Vega進(jìn)程和MFC主進(jìn)程將運(yùn)行在同一臺(tái)PC上,所以主要應(yīng)用于網(wǎng)絡(luò)環(huán)境PC間的進(jìn)程間通信的NetDDE、WindowsSockets、NetBIOS以及RPC都不適合,而通過(guò)磁盤(pán)文件來(lái)進(jìn)行數(shù)據(jù)交換也不可行,這樣就只能直接在內(nèi)存中進(jìn)行通信。因?yàn)樵赩e
轉(zhuǎn)載請(qǐng)注明來(lái)自:http://www.jinnzone.com/weidianziyingyonglw/990.html
上一篇:沒(méi)有了