LabVIEW 程序中的线程 4 - 动态连接库函数的线程


1. CLN 中的线程设置

  

 

LabVIEW <wbr>程序中的线程 <wbr>4 <wbr>- <wbr>动态连接库函数的线程 <wbr>[编写高效率的代码]

 

图1:在 CLN 的配置面板上选择函数运行的线程

 

 

LabVIEW <wbr>程序中的线程 <wbr>4 <wbr>- <wbr>动态连接库函数的线程 <wbr>[编写高效率的代码]

 

图2:不同颜色表示 CLN 不同的线程设置

2. 如何选择合适的线程

    对于在 CLN 中选取何种线程,有一个简单的判断方法。如果你要使用的动态连接库是多线程安全的,就选择可重入方式;否则,动态连接库不是多线程安全的,就选择界面线程方式。
    判断一个动态连接库是不是线程安全的,也比较麻烦。如果这个动态连接库文档中没用明确说明它是多线程安全的,那么就要当他是非线性安全的;如果能看到动态连接库的源代码,代码中存在全局变量、静态变量或者代码中看不到有 lock 一类的操作,这个动态连接库也就肯定不是多线程安全的。

  

  

3. 与 VI 的线程选项相配合

  

    我曾经编写过一个在 LabVIEW 中使用 OpenGL 的演示程序(为了演示我们开发的“Import Shared Library 功能”),对 OpenGL 的调用全部是通过 CLN 方式完成的。由于 OpenGL 的全部操作必需在同一线程内完成,我把所有的 CLN 都设置为在界面线程运行的方式。对 VI 的线程选项没有修改,还是默认的选项。结果程序运行极慢,每秒钟只能刷新一帧图像,CPU 占用 100%。但是作为动画每秒至少25帧才能看着比较流畅。
   

   直到有一天我从同事给我的提供的一些信息中得到了启发,才突然想通,这些 CPU 全部被消耗在线程切换中了。我们调用 OpenGL 方法是为每个 OpenGL API 函数包装一个 API VI,这些 API VI 非常简单,程序框图就只有一个 CLN 节点,调用相应的 OpenGL 函数。由于每个 VI 都是在默认的执行线程中运行,而 CLN 调用的函数却是在界面线程下运行的。所以每次执行一次这样的 API VI,LabVIEW 都要做两次线程切换,从执行线程切换到界面线程,执行完函数,在切换回执行线程。
   

  

    由此,我也想通了另一个问题。就是我曾经发现调用 Windows API 函数遇到的错误信息丢失的问题。在调用某一 Windows API 函数返回值为0时,表示有错误发生了。这时你可以调用 GetLastErr 和 FormatMessage 得到错误代码和信息。但是我经常遇到的问题是:前一个函数明明返回值为0,但是随后调用的 GetLastErr 函数却无法查到错误代码。