Peter Scarfe, Creator of Workers for LabVIEW, 在VIMP中搜索Worker進(jìn)行安裝即可,本文檔基于Workers 3.1.1版本進(jìn)行說(shuō)明。
1. Workers的設(shè)計(jì)背景
雖然LabVIEW可以很容易地以非常高效的方式開(kāi)發(fā)小型和獨(dú)立的任務(wù),但對(duì)大多數(shù)人來(lái)說(shuō),開(kāi)發(fā)一個(gè)更復(fù)雜的多線程應(yīng)用程序,仍然是一個(gè)比較困難且耗時(shí)的過(guò)程。需要多個(gè)獨(dú)立循環(huán)、且健壯、可擴(kuò)展、易于調(diào)試的應(yīng)用程序需要時(shí)間和經(jīng)驗(yàn)去開(kāi)發(fā)。
Actor Framework采用LVOOP封裝設(shè)計(jì),提供了增強(qiáng)的可伸縮性、可擴(kuò)展、和優(yōu)先級(jí)隊(duì)列,但是它對(duì)新手開(kāi)發(fā)人員來(lái)說(shuō)理解相對(duì)復(fù)雜。所以作者希望可以做更多事情來(lái)幫助新手開(kāi)發(fā)人員以一種更簡(jiǎn)單、快速且輕松的方式開(kāi)發(fā)出高質(zhì)量的應(yīng)用程序,而無(wú)需具備LVOOP基礎(chǔ),或是學(xué)習(xí)一些新的不熟悉的架構(gòu),于是在使用廣泛且被大家熟悉理解的QMH框架基礎(chǔ)上,并且為了提高開(kāi)發(fā)效率集成一些腳本工具,便創(chuàng)建了Workers。
作者希望通過(guò)Workers可以提高新手和高級(jí)開(kāi)發(fā)人員的生產(chǎn)力,讓他們以更低復(fù)雜度和更短的時(shí)間開(kāi)發(fā)更大的項(xiàng)目。
2. Workers的特征
2.1 模塊化
一個(gè)Worker就是一個(gè)獨(dú)立的QMH(Queued Message Handler)模塊,類似搭積木一樣將它們組織在一起,通過(guò)多個(gè)Worker的協(xié)作,可以很輕松地創(chuàng)建它們的層次結(jié)構(gòu)來(lái)構(gòu)建應(yīng)用程序的框架。模塊化設(shè)計(jì)還使得它們可以通過(guò)Create/Add Worker Tool被更好的復(fù)用和擴(kuò)展,Workers被設(shè)計(jì)的小而靈活,并且可以被靜態(tài)或動(dòng)態(tài)加載。
2.2 可擴(kuò)展
Workers允許你通過(guò)使用Create/Add Worker Tool快速創(chuàng)建多個(gè)Worker來(lái)構(gòu)建程序的功能框架,大大減少開(kāi)發(fā)時(shí)間和未來(lái)需要擴(kuò)展的工作量,可以很方便地使用其它項(xiàng)目中開(kāi)發(fā)好的Worker模塊,或創(chuàng)建自己的Worker模板在該腳本工具中進(jìn)行使用。
2.3 優(yōu)先級(jí)消息隊(duì)列
參考Actor Framework中消息隊(duì)列設(shè)計(jì)改編而來(lái),性能和限制基本與之一樣。它提供了一個(gè)多優(yōu)先級(jí)的消息隊(duì)列,包括Low、Normal(default)、High、Critical(Framework Only)四個(gè)優(yōu)先級(jí),提供了更加靈活的消息優(yōu)先級(jí)處理方式。
2.4 調(diào)試器
一個(gè)框架的好壞取決于它的調(diào)試器!Workers Debugger一開(kāi)始就是和Worker框架一起開(kāi)發(fā)的,旨在幫助讓運(yùn)行的代碼更加透明且易于導(dǎo)航。Task Manager顯示了所有正在運(yùn)行的Workers的當(dāng)前狀態(tài),并允許你跳轉(zhuǎn)到正在運(yùn)行的克隆副本中以進(jìn)行進(jìn)一步調(diào)試。Message Log按時(shí)間順序列出所有Workers消息處理循環(huán)之間發(fā)送的消息,消息入隊(duì)和出隊(duì)列的時(shí)間和地點(diǎn),以及Workers中哪里發(fā)生了錯(cuò)誤,借助調(diào)試器可以很容易定位問(wèn)題并直接跳轉(zhuǎn)到它們,以便立刻修復(fù)它們。
2.5 層次視圖工具
應(yīng)用程序中所有的Workers的調(diào)用鏈層次關(guān)系是怎樣的?它們是被其它的Worker靜態(tài)還是動(dòng)態(tài)進(jìn)行加載的?層次視圖工具可以為你展示這些信息,通過(guò)平面視圖以樹(shù)狀圖為你展示W(wǎng)orkers之間的關(guān)系。
2.6 分支標(biāo)簽
用來(lái)定義消息處理循環(huán)的分支,它是一個(gè)帶字符串輸出的VI,用來(lái)替代以往用的字符串常量,相比字符串常量更具優(yōu)勢(shì),方便修改,查找跳轉(zhuǎn)追蹤消息流向,在Workers中提供了Quick Drop插件來(lái)自動(dòng)創(chuàng)建,很實(shí)用的設(shè)計(jì)考慮。
2.7 支持使用LVOOP進(jìn)行擴(kuò)展
雖說(shuō)Workers適合沒(méi)有LVOOP基礎(chǔ)的新手實(shí)用,但了解LVOOP相關(guān)知識(shí)可以更好地實(shí)用Workers框架,它采用LVOOP進(jìn)行設(shè)計(jì),提供了非面向?qū)ο?a href="http://hljzzgx.com/v/tag/1315/" target="_blank">編程所不具有的一些優(yōu)點(diǎn),所有的Workers都繼承自Workers.lvclass,主要的一些公共API都包含其中,框架已經(jīng)幫我們實(shí)現(xiàn)好了,大大減少了重復(fù)代碼,當(dāng)開(kāi)發(fā)的多個(gè)Workers有相同的行為時(shí),可以引入中間層,新增公共方法代碼或重新Workers的公共API,這樣就可以被繼承自它的Workers使用了。
3. Worker的構(gòu)成
3.1 Worker的定義
簡(jiǎn)單定義:模塊化的消息隊(duì)列處理程序
高級(jí)定義:一個(gè)繼承自Workers.lvclass的類,其中包含一個(gè)消息處理程序及其相關(guān)支持代碼和控件。
每個(gè)新創(chuàng)建的Worker都包含下面幾個(gè)部分:
Initialization Data.ctl:自定義簇,Worker在初始化時(shí)期望接收的任何數(shù)據(jù)的定義。
Main.vi:包含QMH的VI,也就是Worker的核心程式碼。
3.2 Workers的層次關(guān)系
典型的應(yīng)用程序都是由多個(gè)Worker分層組合構(gòu)建而成,一個(gè)Worker可以在Main.vi中調(diào)用一個(gè)或多個(gè)其它的Workers,如下圖由三個(gè)Workers構(gòu)成:
Worker A:最頂層的Worker,通常稱為 "Head Worker",應(yīng)用程序通過(guò)啟動(dòng)它的Main.vi開(kāi)始運(yùn)行。它也被稱之為 Sub Worker 的 "Manager",它負(fù)責(zé)管理它的所有Sub Workers的啟動(dòng)、初始化和關(guān)閉。
Worker B / Worker C:它們的Main.vi在Worker A中被調(diào)用,因而被稱作是Worker A的 "Sub Worker"。
Manager 和 Sub Worker兩個(gè)術(shù)語(yǔ)用來(lái)描述Workers直接調(diào)用與被調(diào)用者之間的關(guān)系。
3.3 Workers中的重要分支(框架需要,不能刪除)
3.3.1 Default
QMH中的默認(rèn)分支,里面有調(diào)用一個(gè)叫Common Case.vi的VI,其中包含了所有Workers的一些公共代碼分支,框架需要用到必須存在。
3.3.2 Initialize
Worker運(yùn)行起來(lái)后會(huì)第一個(gè)被執(zhí)行的分支,在該分支中會(huì)接收到它的 Manager 發(fā)送給它的一些初始化數(shù)據(jù),也就是在 Initialization Data.ctl 中定義的數(shù)據(jù)。在該分支中會(huì)調(diào)用 Write(Set) Initialization Data - Worker Name.vi 將初始化數(shù)據(jù)加載到緩存中 (如果需要的話),隨后會(huì)調(diào)用Initialize subWorkers.vi 給所有的 Sub Workers發(fā)消息執(zhí)行 “Initialize"分支,如果已經(jīng)緩存了初始化數(shù)據(jù)會(huì)一起捆綁到消息中被發(fā)送過(guò)去。
如果該Workers沒(méi)有 Sub Workers,Initialize subWorkers.vi會(huì)調(diào)用執(zhí)行 "All subWorkers Initialized" 分支。
3.3.3 All subWorkers Initialized
當(dāng)所有 Sub Workers 都初始化完成時(shí)會(huì)執(zhí)行該分支(當(dāng)一個(gè)Worker初始化完成時(shí)它會(huì)調(diào)用 Initialize Notify.vi 通知它的 Manager Worker),如果你想在所有 Sub Worker初始化完成后執(zhí)行某些任務(wù),可以在該分支中進(jìn)行。
3.3.4 Start Exiting
通過(guò)調(diào)用 Start Exiting Worker.vi 會(huì)執(zhí)行該分支,在該分支中會(huì)調(diào)用 Start Exiting subWorkers.vi 通知所有 Sub Workers 執(zhí)行 ”Start Exiting“ 分支開(kāi)始退出操作。
如果該Workers沒(méi)有 Sub Workers,Start Exiting subWorkers.vi 會(huì)調(diào)用執(zhí)行 "All subWorkers Exited" 分支。
3.3.5 All subWorkers Exited
當(dāng)所有的 Sub Worker都成功退出時(shí),框架會(huì)自動(dòng)執(zhí)行該分支(當(dāng)一個(gè)Worker結(jié)束運(yùn)行是它會(huì)調(diào)用 Exited Notify and Cleanup.vi 通知它的 Manager Worker),如果你想在所有 Sub Worker都結(jié)束后執(zhí)行某些任務(wù),可以在該分支中進(jìn)行。
當(dāng)你想退出Worker停止運(yùn)行時(shí),需要調(diào)用 Exit.vi (stop loop? 會(huì)賦值 True),它會(huì)引起 MHL (和 EHL ,如果有的話) 的結(jié)束,從而結(jié)束Worker的運(yùn)行。
3.4 初始化和退出的時(shí)序
通過(guò)一個(gè)包含4個(gè)Workers的簡(jiǎn)單應(yīng)用來(lái)進(jìn)行說(shuō)明。
3.4.1 初始化時(shí)序
應(yīng)用程序的初始化通常是從 Head Worker 的 “Initialize” 分支執(zhí)行開(kāi)始。整個(gè)初始化過(guò)程大致如下:
通過(guò) Launcher VI 啟動(dòng) Worker A。
Worker A執(zhí)行 “Initialize” 分支,然后調(diào)用 Initialize subWorkers.vi。
所有Worker A的 Sub Worker 都執(zhí)行 “Initialize” 分支,然后它們分別調(diào)用 Initialized Notify.vi 通知 Worker A它們已經(jīng)完成初始化。
Worker A 接著就會(huì)執(zhí)行 “All subWorkers Initialized" 分支,最后它也會(huì)調(diào)用 Initialized Notify.vi 告知框架自己已經(jīng)完成初始化。
3.4.2 退出時(shí)序
應(yīng)用程序的退出通常是從 Head Worker 的 “Start Exiting’” 分支執(zhí)行開(kāi)始。整個(gè)初始化過(guò)程大致如下:
在Worker A中,用戶通過(guò)調(diào)用 Start Exiting Worker.vi 開(kāi)始執(zhí)行退出操作,如在EHL的 "Panel Close?" 分支中調(diào)用。
Worker A執(zhí)行 “Start Exiting” 分支,然后調(diào)用 Start Exiting subWorkers.vi。
所有Worker A的 Sub Worker 都執(zhí)行 “Start Exiting” 分支,然后它們退出時(shí)分別調(diào)用 Exited Notify and Cleanup.vi 通知 Worker A它們已經(jīng)退出停止運(yùn)行。
Worker A 接著就會(huì)執(zhí)行 “All subWorkers Exited" 分支,最后它也會(huì)調(diào)用 Exited Notify and Cleanup.vi 告知框架自己也已經(jīng)退出停止運(yùn)行。
4. Workers中的消息
Workers中使用了兩種類型的消息,標(biāo)準(zhǔn)消息(異步)和回調(diào)消息(異步或同步)。
4.1 標(biāo)準(zhǔn)消息
標(biāo)準(zhǔn)消息是異步的,可以通過(guò)使用Enqueue Standard Message.vi來(lái)進(jìn)行發(fā)送。該VI是一個(gè)多態(tài)VI,包括兩種可選的VI:
Enqueue Message to Self v2.vi
給當(dāng)前的worker自己發(fā)送消息。
Enqueue Message to Queue.vi
給指定隊(duì)列的Worker發(fā)送消息。
4.2 回調(diào)消息
接收方Worker在收到消息后,可以直接向發(fā)送方Worker發(fā)送回復(fù)消息,而無(wú)需訪問(wèn)其隊(duì)列。
框架中支持兩種類型的回調(diào)消息,通過(guò)調(diào)用Enqueue Callback Message.vi來(lái)進(jìn)行發(fā)送,該VI是一個(gè)多態(tài)VI,包含四種可選的VI:
Enqueue and Collect.vi(同步)
給指定隊(duì)列的Worker發(fā)送同步的”Callback“消息,該線程想被掛起直到收到接收方Worker回復(fù)的 ”Callback Reply“消息或超時(shí)(默認(rèn)5000ms)。
Enqueue and Collect - Silent Mode.vi (靜默模式)
Enqueue and Forget.vi(異步)
給指定隊(duì)列的Worker發(fā)送異步的”Callback“消息。
Enqueue and Forget - Silent Mode.vi (靜默模式)
通過(guò)Get Callback Message.vi找到回調(diào)消息并保存,然后調(diào)用 Callback Reply.vi給發(fā)送方Worker發(fā)送回復(fù)消息,框架中提供了Callback Easy Reply.vi方法直接使用。
4.3 靜默模式
上述消息入隊(duì)列VI都支持靜默模式(帶有靜音的圖標(biāo)),功能上沒(méi)有區(qū)別,只是使用該模式發(fā)送的消息不會(huì)記錄到調(diào)試器的消息日志中,當(dāng)你不想調(diào)試器被一些重復(fù)且頻繁發(fā)送的消息填滿時(shí),使用該模式將會(huì)很有用。
4.4 消息的構(gòu)成
每條消息都包含一些特定的數(shù)據(jù)類型,它們會(huì)打包在一起進(jìn)行發(fā)送,如下所示:
其中包括:
Case Lable
指定接收方Worker的MHL中分支名稱,通過(guò)Quick Drop 進(jìn)行創(chuàng)建。
Data(Optional)
將任意數(shù)據(jù)類型轉(zhuǎn)成變體進(jìn)行發(fā)送,接收方需要按照指定的類型進(jìn)行轉(zhuǎn)換,可選。
Auxiliary(Optional)
作為附加數(shù)據(jù)進(jìn)行發(fā)送,與Data類似,可選。
MetaData(hidden)
框架自身需要用到的一些數(shù)據(jù),用來(lái)標(biāo)識(shí)消息的發(fā)送方和接收方,這些數(shù)據(jù)會(huì)被發(fā)送到調(diào)試器中。
4.5 消息優(yōu)先級(jí)
框架中設(shè)計(jì)的初始化和退出時(shí)序中使用的消息優(yōu)先級(jí)是“Critical”,該優(yōu)先級(jí)不對(duì)開(kāi)發(fā)人員開(kāi)發(fā),原因就是當(dāng)Worker的消息隊(duì)列過(guò)載時(shí),框架仍然能夠搶占消息并關(guān)閉應(yīng)用程序,從而提高程序的可靠性及性能。
4.6 Case Label
創(chuàng)建Case Label
確保Worker的Main.vi程序框圖窗口處于激活狀態(tài),并將MHL中的條件分支切換到對(duì)應(yīng)的分支,比如“Inset to Main Panel"。
2. 激活Quick Drop,按Ctrl + 9進(jìn)行創(chuàng)建。
分支跳轉(zhuǎn)
選中要跳轉(zhuǎn)的Case Label。
激活Quick Drop,按Ctrl + 8,將會(huì)自動(dòng)跳轉(zhuǎn)到對(duì)應(yīng)的條件分支中。
5. Worker的加載
一個(gè)Worker可以以靜態(tài)或動(dòng)態(tài)兩種方式被另一個(gè)Worker進(jìn)行加載。
5.1 靜態(tài)加載
大部分時(shí)候,通過(guò)腳本工具 “Create/Add Worker" 創(chuàng)建或添加的 Sub Worker會(huì)自動(dòng)以靜態(tài)的方式在 Manager Worker中進(jìn)行加載。靜態(tài)加載是用得最多的方式。
5.2 動(dòng)態(tài)加載
有時(shí)你期望通過(guò)編程的方式加載一些沒(méi)有事先指定的Worker,那么使用動(dòng)態(tài)加載會(huì)很有用,框架中提供了Dynamically Load Worker.vi來(lái)實(shí)現(xiàn)該功能,一旦Worker被動(dòng)態(tài)加載,它會(huì)自動(dòng)集成到Manager Worker中,其行為方式將于靜態(tài)加載的Worker一致。
6. Workers中的調(diào)試器
Workers調(diào)試器在使用該框架開(kāi)發(fā)的應(yīng)用程序中扮演著不可或缺的一部分。不論一個(gè)框架多么好用,如果它創(chuàng)建的代碼難以導(dǎo)航和調(diào)試,那么框架帶來(lái)的高效性將大打折扣。調(diào)試器必須在Workers應(yīng)用程序運(yùn)行之前啟動(dòng),可以直接通過(guò)菜單 “Tools >> Workers tools...”啟動(dòng),或以編程的方式通過(guò)調(diào)用Debugger Loader.vi進(jìn)行加載。
6.1 Task Manager
在Task Manager頁(yè)面可以看到所有加載的Workers層級(jí)列表,并行能看到它們的Clone ID (Workers的Main.vi是共享副本的) 和狀態(tài)。
框架中定義的一些狀態(tài)有:
Queue Created
在Manager Worker中調(diào)用執(zhí)行Setup subWorkers.vi 已經(jīng)完成了Worker的消息隊(duì)列創(chuàng)建(或是在Head Worker中調(diào)用 Setup Head Worker.vi完成了Head Worker的消息隊(duì)列創(chuàng)建)。
Pre-initialized
Worker的Main.vi已經(jīng)被加載,而且能將收到的消息出隊(duì)列,處于初始化前的一個(gè)就緒狀態(tài)。
Initialized called
Worker已經(jīng)跳轉(zhuǎn)到“Initialize”分支執(zhí)行。
Initialized
Worker已經(jīng)通過(guò)調(diào)用Initialized Notify.vi告知它的Manager Worker自己已經(jīng)完成了初始化。
Start Exiting called
Worker已經(jīng)跳轉(zhuǎn)“Start Exiting”分支開(kāi)始執(zhí)行(通過(guò)調(diào)用Start Exiting Worker.vi或是在Manager Worker中調(diào)用Start Exiting subWorkers.vi.)。
Exited
The Worker已經(jīng)通過(guò)調(diào)用Exited Notify and Cleanup.vi告知它的Manager Worker自己已經(jīng)成功退出。
Stopped (Critical Error)
Worker中已經(jīng)發(fā)生了嚴(yán)重的錯(cuò)誤,Worker已經(jīng)停止且不能再被訪問(wèn)。
(Aborted)
當(dāng)應(yīng)用程序提前終止時(shí),追加到上述狀態(tài)的字符串。
6.2 Task Manager的右鍵菜單
Open Running VI
會(huì)顯示當(dāng)前正在運(yùn)行的Workers的 Main.vi副本程序框圖,如果該VI不再運(yùn)行,那么將打開(kāi)可編輯模式的Main.vi。
Filter as Enque Worker
右鍵選中的Worker作為 Enque Worker對(duì)Message Log頁(yè)面中的信息進(jìn)行過(guò)濾顯示。
Filter as Deque Worker
右鍵選中的Worker作為 Deque Worker對(duì)Message Log頁(yè)面中的信息進(jìn)行過(guò)濾顯示。
6.3 Message Log
每當(dāng)一條消息在Worker中出隊(duì)列時(shí),消息中的MetaData都會(huì)被發(fā)送到調(diào)試器中記錄,在該頁(yè)面提供了以下功能:
按照時(shí)間先后順序顯示MHL之間的消息流向。
顯示應(yīng)用程序中的錯(cuò)誤,并告知發(fā)送的時(shí)間和位置。
允許用戶直接跳轉(zhuǎn)到Message Log中顯示的任何Worker的條件分支中。
Enque Worker
發(fā)生消息的Worker的ID。
Enque Case
Worker中發(fā)送消息的分支。
Deque Worker
接收消息的Worker的ID。
Deque Case
Worker中接收消息的分支。
Message
一個(gè)字符串可以作為消息發(fā)送到調(diào)試器中. 消息被發(fā)送到調(diào)試器中有以下方式:
用戶通過(guò)調(diào)用 Send Debugger Message.vi 進(jìn)行發(fā)送。(在Workers的函數(shù)選板中可以找到)。
當(dāng)框架運(yùn)行時(shí)發(fā)生了錯(cuò)誤,被Error Handler.vi檢測(cè)到時(shí)框架會(huì)自動(dòng)發(fā)送到調(diào)試器。
6.4 Message Log的右鍵菜單
Filter String (Double Click)
該列會(huì)通過(guò)單元格中的字符串進(jìn)行過(guò)濾,或在指定的單元格進(jìn)行雙擊即可執(zhí)行相同的操作。
Open Running VI
顯示當(dāng)前正常運(yùn)行的Worker’s Main.vi (clone) 的程序框圖。
Go to Case
會(huì)跳轉(zhuǎn)到Workers編輯模式的Main.vi中特定分支,由鼠標(biāo)單擊時(shí)的單元格中分支名稱決定。(該操作對(duì)Worker中的基本分支無(wú)效)
7. Workers Tools
Tools >> Workers tools...
Create/Add Worker
添加Sub Worker
Worker層級(jí)視圖
Worker的調(diào)試器界面
8. Workers Demo
產(chǎn)品老化測(cè)試,10個(gè)槽并行測(cè)試,記錄老化過(guò)程中的溫度、電壓和電流,每個(gè)槽的數(shù)據(jù)需在界面中顯示,并保存所有老化數(shù)據(jù),支持?jǐn)?shù)據(jù)按時(shí)間和槽進(jìn)行查詢。
審核編輯:劉清
-
LabVIEW
+關(guān)注
關(guān)注
1970文章
3654瀏覽量
323305 -
API
+關(guān)注
關(guān)注
2文章
1499瀏覽量
61961 -
調(diào)試器
+關(guān)注
關(guān)注
1文章
303瀏覽量
23716
原文標(biāo)題:Workers框架入門(mén)教程
文章出處:【微信號(hào):LabVIEW QT 修煉之路,微信公眾號(hào):LabVIEW QT 修煉之路】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論