Critical Security Update
To help protect your systems, customers using NI driver software 2026 Q2 or earlier should visit ni.com/ni-pal-update and follow the recommended actions.
精心設計的 LabVIEW 應用程式是充分提升軟體開發與維護效率的關鍵。 本文件介紹 LabVIEW 中與軟體設計息息相關的基本結構、設計模式與架構。文件內容並不全面,但可提供有助益的入門指引,介紹一些最常見的 LabVIEW 軟體設計元素。如需詳細資訊,請參閱文件中註明的連結。
下列各節分別說明在 LabVIEW 程式設計中用於完成某項特定作業的常見結構。熟悉這些基本結構能幫助您更容易分辨及了解各項結構在 LabVIEW 應用程式中的用途。
類型定義 (通常簡稱「typedef」) 用於指定在整個應用程式中完全保持一致定義的資料類型。例如,下圖為叢集類型的定義:
將這個 typedef 拖曳到人機介面或程式方塊圖上時,它會以叢集形式出現,但其端子和常數的左上角會顯示一個黑色三角形:
typedef 非常適合用於在應用程式中定義一致的類型。為了說明這一點,假設在 typedef 中新增一個參數(如本範例中的設定檔路徑),注意會發生什麼樣的變化:
只要在單一位置修改 typedef (單一位置指原始 typedef .ctl 檔案),此更改就會自動傳播到整個應用程式:
如果叢集並非 typedef,則需要逐一手動更新整個應用程式中該叢集 (人機介面和程式方塊圖) 的所有執行個體。除極少數情況外,您在編寫 LabVIEW 應用程式時建立的叢集和列舉,均建議使用 typedef 定義資料類型。
使用 typedef,就能透過單一來源管理共用資料類型,提升程式碼的可維護性。
Event 結構用於回應 LabVIEW 程式方塊圖中的使用者介面事件和程式設計事件。舉例來說,您可以註冊一個事件程式方塊圖,使其在人機介面控制值出現變化時執行。您也可以註冊使用 Generate User Event 函式以程式設計方式在程式方塊圖上產生的事件。
Event 結構通常會放在 While 迴圈內,讓程式碼可以在程式碼執行期間回應多個事件。可以將 Event 結構設定成針對想要偵測的不同事件使用不同的框架。每個事件框架皆包含會在事件發生時執行的處理程式碼。
探索 LabVIEW 隨附的下列專案,了解幾個示範使用者介面事件和程式設計事件的範例:
功能性全域變數 (也稱為「FGV」、「全域 LabVIEW 2 樣式」或「動作引擎」) 是一種資料儲存機制。 FGV 會將資料儲存在未初始化移位暫存器或未初始化回饋節點中,讓您在應用程式中的任何位置 (即「全域」) 都能存取該資料。 下方所示為基本 FGV VI 的程式方塊圖,其中包含 Data in (資料輸入) 與 Data out (資料輸出),以及包含兩項動作 (「Set」(設定) 和「Get」(取得)) 的「Operation」(作業) 列舉:
這個簡單的取得/設定 FGV 提供的功能,相當於使用一個全域變數。實際上,除了「設定」和「取得」以外,FGV 可能還會執行其他功能。
您可以使用 FGV 儲存參考並執行更精密的作業。 舉例來說,請觀察下方的檔案 I/O FGV (示範使用未初始化移位暫存器而非回饋節點)。 此 FGV 會在連續呼叫之間儲存檔案參考,並在單一 VI 中執行多種不同的操作 (開啟、讀取、寫入和關閉)。
請注意,FGV 和全域變數一樣容易受競態條件影響。一般而言,請避免在程式碼中的多個位置寫入全域資料。
子面板是一種人機介面控制元件,能顯示另一個 VI 的人機介面。 使用子面板可以設計動態使用者介面,只要指定在子面板中顯示另一個 VI,就能換掉 UI 中的部分完整區段。子面板也有助於開發模組化應用程式,也就是將人機介面項目依邏輯分組封裝在各自獨立的 VI 中。 透過此設計,使用者可以修改顯示在子面板中的個別 VI,不需要更改其他顯示 VI 或主應用程式 VI 的程式碼。
下方範例用於掃描外掛程式 VI 的資料夾,並使用這些外掛程式填充文字環。當您在文字環中選擇一個項目時,會將對應的外掛程式 VI 插入主 VI 內的子面板中。 這個結構用於在磁碟上新增外掛程式 VI,不需對主 VI 進行任何更改。
執行 LabVIEW 隨附的下列範例,嘗試更多使用子面板的方式:
根據預設,LabVIEW 中的 VI 屬於非重入 VI。這表示一次只能執行一個 VI 執行個體。因此,在下圖中,「Process.vi」的每一個子 VI 執行個體,都要等到另一個執行結束後才能執行。
如果希望 VI 的多個執行個體能夠同時執行,就必須將該 VI 設為重入 VI。若要執行此操作,請進入 File > VI Properties > Execution (檔案 > VI 屬性 > 執行),將「Reentrancy」(重入) 設定變更為 Shared clone reentrant execution (共用複本重入執行) 或 Preallocated clone reentrant execution (預先配置複本重入執行)。
將 VI 變更為重入 VI 後,多個執行個體就能同時執行:
在下列情況下,可以考慮將 VI 設為重入 VI:
請注意,功能性全域變數幾乎一律具有非重入特性,因為這些變數會保留整個應用程式需要共用的全域狀態資料。
執行 LabVIEW 隨附的下列範例,使用重入 VI 進行實驗:
從某個 VI 呼叫另一個 VI 時,通常會使用一般的子 VI 呼叫。呼叫子 VI 時,呼叫程式圖必須等到子 VI 執行結束才能繼續執行。這是同步呼叫的範例。
不過,在某些情況下,應用程式可能會要求您啟動子 VI,但在子 VI 繼續執行時繼續呼叫 VI 的執行作業。這是非同步呼叫的範例。使用非同步 VI 呼叫,就能同時動態執行任意數量的 VI。再者,使用重入 VI 可以生成同一個 VI 的無數個執行個體,並且讓這些執行個體以非同步方式執行。
在下方範例中,呼叫 VI 會以非同步方式呼叫重入 Process.vi 的多個執行個體。 每個 VI 獨立執行,執行結束時就會將資料傳回呼叫 VI。 呼叫 VI 可以同時執行其他程式方塊圖程式碼,不必等待 Process VI 執行個體執行結束。
探索 LabVIEW 隨附的下列專案,其中有多個範例說明非同步 VI 呼叫的更多細節:
在 LabVIEW 中,使用 LabVIEW 類別有助於加速進行物件導向程式設計。 LabVIEW 物件導向程式設計使用 C++ 和 Java 等其他物件導向程式設計語言的概念,包括類別結構、封裝與繼承。您可以使用這些概念建立更易於維護及修改的程式碼,不會影響應用程式中的其他程式碼區段。LabVIEW 可以應用許多物件導向的設計模式。 相關內容說明請參考將常見的物件導向 (OO) 設計模式應用於 LabVIEW 文件。
探索 LabVIEW 隨附的下列資料夾中的專案,其中包含幾項範例,介紹使用 LabVIEW 類別進行程式設計的基本概念:
設計模式是用於執行同步或非同步程式碼的理論機制。多數實際架構 (見下方章節) 會採用一或多種設計模式作為核心執行機制。了解本節所述設計模式的行為,有助於進一步理解以這些設計模式為基礎建立的更複雜架構的行為。
狀態機是執行狀態圖或流程圖的 LabVIEW 程式方塊圖。指定的「狀態」包含決定下一個待執行狀態的程式方塊圖邏輯。某些狀態機由使用者介面驅動,其中的使用者輸入或區塊圖邏輯可以決定下一個要執行的狀態。
基本的 LabVIEW 狀態機包含下列主要元件:
探索 LabVIEW 隨附的下列專案,深入了解狀態機相關資訊:
在 LabVIEW 中使用簡易狀態機專案範本建立自己的狀態機專案:瀏覽 LabVIEW File (檔案) 功能表 >> Create Project (建立專案) >> Simple State Machine (簡易狀態機)。您可以修改這個範本,再據以開始建立自己的應用程式。
產生者/消耗者設計模式說明如何使用佇列在以不同速率執行的多個迴圈之間共用資料。包含一個 Enqueue Element 函式的迴圈是「產生者」,包含一個 Dequeue Element 函式的迴圈則是「消耗者」。若迴圈執行速率不同,使用佇列能確實避免失去資料。
關於產生者/消耗者設計模式,需要注意的一點是,該模式仍以理論為主。在實際中,實際程式碼中很少使用基本的產生者/消耗者模式。相較之下,使用佇列式訊息處理器的情況會更普遍。
請執行 LabVIEW 隨附的下列範例,深入了解使用佇列在迴圈之間共用資料的相關資訊:
佇列式訊息處理器 (QMH) 是產生者/消耗者設計模式的一種實作方式,其中也包含事件結構,用於處理產生的使用者介面事件與程式設計事件。 事件處理迴圈 (EHL) 含事件結構,負責將訊息加入訊息處理迴圈 (MHL) 的訊息佇列 (即產生),而 MHL 則會自佇列移除 (消費) 這些訊息。 MHL 亦可根據需要自行產生訊息。 此處的「訊息」是指叢集,內含一個字串 (用於控制 MHL 中的條件結構) 以及一個變數 (可變資料類型),該變數包含任何類型的該訊息專用資料。 在 QMH 中,MHL 也能透過使用者事件回傳訊息到 EHL。
探索 LabVIEW 隨附的下列專案,深入了解 QMH:
您可以在 LabVIEW 中透過佇列式訊息處理器專案範本建立自己的 QMH 架構專案:瀏覽 LabVIEW File (檔案) 功能表 >> Create Project… (建立專案…) >> Queued Message Handler (佇列式訊息處理器)。
大型 LabVIEW 應用程式必須架構完善,才能靈活擴充且易於維護。
試著想像一個純理論性質的 LabVIEW 應用程式,其功能是用於測試某個裝置。應用程式中會包含程式碼,用於設定應用程式、與裝置連線、進行量測、顯示資料、記錄資料、處理錯誤狀況,以及執行許多其他功能。
若將此應用程式前述的所有功能全數寫在同一個 LabVIEW 程式方塊圖中,就無法獨立開發、測試及除錯其各項功能。 舉例來說,如果記錄程式碼出現問題,就必須執行整個應用程式,無法單獨針對記錄功能進行除錯。此外,變更記錄程式碼可能會不慎影響應用程式的其他部分,因為應用程式中的所有部分均位於同一個 VI。
上述各項功能較適合以非同步流程執行,讓每個功能各自採用模組化設計,能夠獨立開發、測試與除錯。各流程之間還必須要有穩定的通訊機制。
用於實作 LabVIEW 程式碼來促進這種模組化非同步設計的結構化方法稱為架構。部分 LabVIEW 團隊會開發自己專用的架構。這項作業並不容易,因為要實作一個成功的非同步 LabVIEW 應用程式,在程式碼架構開發與訊息傳遞方面都必須考量許多因素、克服各種陷阱和遵從諸多注意事項。另外,要建立一個穩定架構必須運用到大量樣板程式碼,因此,架構內必須要有足夠的工具,能自動處理重複性作業 (協助開發人員避免在手動撰寫架構程式碼時發生錯誤)。
值得慶幸的是,目前已有多個組織 (包括 NI 內部和外部) 將自己的消費者級架構提供給 LabVIEW 社群,完成了這項困難的工作。目前最常用的 LabVIEW 架構有兩種:行動元框架和 DQMH。
行動元框架 (AF) 是 NI 支援且 LabVIEW 中隨附的一種架構。這是佇列式訊息處理器 (QMH) 的一種物件導向的實作方式。相較於條件結構和 Enqueue Element 函式中的訊息處理迴圈框架,訊息類別提供「Do」方法 VI,在 Actor Core VI 內執行特定程式碼。
以類別為基礎的 AF 設計提供一個可擴充的架構,用於實作可繼承父行動元行為的子行動元,這是以條件結構為基礎的標準 QMH 方法所無法實現的。此外,由於架構採用物件導向設計,所有核心架構功能 (初始化、訊息傳遞、錯誤處理等) 都能在特定行動元中進行擴充或覆寫。
探索 LabVIEW 隨附的下列專案,深入了解行動元框架:
使用行動元框架專案範本在 LabVIEW 中建立自己的 AF 架構專案:瀏覽 LabVIEW File (檔案) 功能表 >> Create Project… (建立專案…) >> Actor Framework (行動元框架)。
請注意,要成功運用行動元框架,必須具備扎實的物件導向程式設計基礎,並且充分接受其相關教學、理解架構本身的概念。我們提供許多與 AF 教育訓練相關的資源。其中最熱門的幾項包括:
當您開始在自己的應用程式中採用 AF 架構時,歡迎加入行動元框架 – NI 社群使用者群組,在那裡和其他使用者交流互動、發問,以及與其他程式設計師討論最佳實務。
Delacor 佇列式訊息處理器 (DQMH®) 採用與標準 QMH 類似的機制在特定流程 (或稱「模組」) 中通訊,而非同步模組之間的通訊則是透過使用者事件進行。雖然 DQMH 架構中確實有一些小元件採用了 LabVIEW 類別,但它並非物件導向架構。
DQMH 是由 DQMH Consortium 所開發並負責維護的第三方架構。原始 DQMH 設計團隊的主要目標,是為 LabVIEW 社群提供一個免費的架構,讓具備 CLAD/CLD 程度的開發人員能夠使用。
您可以使用 VI Package Manager 安裝 DQMH。
安裝好 DQMH 組合後,您可以探索下列專案,開始深入了解:
我們提供許多 DQMH 教育訓練資源。 當您開始在自己的應用程式中採用 DQMH 時,歡迎加入 DQMH Consortium Toolkits – NI 社群使用者群組,在那裡和其他使用者交流互動、發問,以及與其他程式設計師討論最佳實務。
DQMH® 是 DQMH Consortium, LLC 的註冊商標。
AF 與 DQMH 是全球最受歡迎的 LabVIEW 架構,但並非只有這些架構。我們還為 LabVIEW 社群提供了其他架構,包括: