- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
LabVIEW 程序中的线程 4 - 动态连接库函数的线程
四、动态连接库函数的线程
1. CLN 中的线程设置
LabVIEW 可以通过 CLN(Call Library Function Node)节点来用动态连接库中的函数,在 Windows 下就是指 .DLL 文件中的函数。用户可以通过 CLN 节点的配置面板来指定被调用函数运行所在的线程。相对于 VI 的线程配置,CLN 的线程选项非常简单,只有两项:界面线程(Run in UI thread)和可重入方式(reentrant)。(新版本 LabVIEW 把这里的 reentrant 改为 Run in any thread 了)
图1:在 CLN 的配置面板上选择函数运行的线程
在 LabVIEW 的程序框图上直接就可以看出一个 CLN 节点是选用的什么线程。如果是在界面线程,则节点颜色是较深的橘红色的;如果是可重入方式的,节点是比较淡的黄色。
图2:不同颜色表示 CLN 不同的线程设置
2. 如何选择合适的线程
对于在 CLN 中选取何种线程,有一个简单的判断方法。如果你要使用的动态连接库是多线程安全的,就选择可重入方式;否则,动态连接库不是多线程安全的,就选择界面线程方式。
判断一个动态连接库是不是线程安全的,也比较麻烦。如果这个动态连接库文档中没用明确说明它是多线程安全的,那么就要当他是非线性安全的;如果能看到动态连接库的源代码,代码中存在全局变量、静态变量或者代码中看不到有 lock 一类的操作,这个动态连接库也就肯定不是多线程安全的。
选择了可重入方式,LabVIEW 会在最方便的线程内运行动态连接库函数,一般会与调用它的 VI 运行在同一个线程内。因为 LabVIEW 是自动多线程的语言,它也很可能会把动态连接库函数分配一个单独的线程运行。如果程序中存在没有直接或间接先后关系的两个 CLN 节点,LabVIEW 很可能会同时在不同的线程内运行它们所调用的函数,也许是同一函数。对于非多线程安全的动态连接库,这是很危险的操作。很容易引起数据混乱,甚至是程序崩溃。
选择界面线程方式:因为 LabVIEW 只有一个界面线程,所以如果所有的 CLN 设置都是界面线程,那么就可以保证这些 CLN 调用的函数肯定全部都运行在同一线程下,肯定不会被同时调用。对于非多线程安全的动态连接库,这就保证了它的安全。
3. 与 VI 的线程选项相配合
如果你的程序中大量频繁的调用了动态连接库函数,那么效率就是一个非常值得注意的问题了。
我曾经编写过一个在 LabVIEW 中使用 OpenGL 的演示程序(为了演示我们开发的“Import Shared Library 功能”),对 OpenGL 的调用全部是通过 CLN 方式完成的。由于 OpenGL 的全部操作必需在同一线程内完成,我把所有的 CLN 都设置为在界面线程运行的方式。对 VI 的线程选项没有修改,还是默认的选项。结果程序运行极慢,每秒钟只能刷新一帧图像,CPU 占用 100%。但是作为动画每秒至少25帧才能看着比较流畅。
我开始试图用 LabVIEW 的 profile 工具来查找效率低下的 VI,结果居然查找不到。在 Profile Performance and Memory 工具上显示的 CPU 占用时间只有一点点。这个工具竟然显示不出程序中最耗时的操作在哪里,自然我也对如何优化这个程序无从下手了。后来这个演示程序被搁置了一段时间。
直到有一天我从同事给我的提供的一些信息中得到了启发,才突然想通,这些 CPU 全部被消耗在线程切换中了。我们调用 OpenGL 方法是为每个 OpenGL API 函数包装一个 API VI,这些 API VI 非常简单,程序框图就只有一个 CLN 节点,调用相应的 OpenGL 函数。由于每个 VI 都是在默认的执行线程中运行,而 CLN 调用的函数却是在界面线程下运行的。所以每次执行一次这样的 API VI,LabVIEW 都要做两次线程切换,从执行线程切换到界面线程,执行完函数,在切换回执行线程。
线程切换是比较耗时的。我的演示程序刷新一帧要调用大约两千次 OpenGL API VI,总耗时接近一秒。
解决这个问题,要么把所有 API VI 中的 CLN 都改为可重入方式,但编写程序时要保证所有被调用的函数都运行在同一线程内,这比较困难。比较容易实现的是,把程序中对 OpenGL 操作相关的 VI 也全部都设置为在界面线程下运行。我选择的就是后一种方法。改进后的程序,每秒钟画30帧图像也不会占满 CPU。
由此,我也想通了另一个问题。就是我曾经发现调用 Windows API 函数遇到
文档评论(0)