LabWindows?/CVI中的多线程技术
检测对GetPointerToVarName的不匹配调用
可以通过DefineThreadSafeScalarVar和DefineThreadSafeArrayVar的最后一个参数(maxGetPointerNestingLevel),来指定最大数目的嵌套调用。通常可以把这个参数设为0,这样GetPointerToVarName在检测到同一线程中对GetPointerToVarName的两次连续调用而中间没有对ReleasePointerToVarName进行调用时,就会报出一个运行错误。例如,下面的代码在第二次执行的时候会报出run-time error的错误,因为它忘记了调用ReleasePointerToCount函数。
int IncrementCount (void) |
如果代码中必须对GetPointerToVarName进行嵌套调用时,那么可将maxGetPointerNestingLevel参数设为一个大于零的整数。例如,下面的代码将maxGetPointerNestingLevel参数设定为1,因此它允许对GetPointerToVarName进行一级嵌套调用。
DefineThreadSafeScalarVar (int, Count, 1); |
如果不知道GetPointerToVarName的最大嵌套级别,那么请传递TSV_ALLOW_UNLIMITED_NESTING来禁用对GetPointerToVarName函数的不匹配调用检查。
线程安全队列
使用LabWindows/CVI Utility Library的线程安全队列,可以在线程间安全地传递数据。当需要用一个线程来采集数据而用另一个线程来处理数据时,这种技术非常有用。线程安全队列在其内部处理所有的数据锁定。通常说来,应用程序中的辅助线程获取数据,而主线程在数据可用时读取数据然后分析并/或显示数据。下面的代码显示了线程如何使用线程安全队列将数据传递到另外一个线程。在数据可用时,主线程利用回调函数来读取数据。
int queue; |
6. 避免死锁
当两个线程同时等待对方持有的线程锁定对象时,代码就不能继续运行了。这种状况被称为死锁。如果用户界面线程发生死锁,那么它就不能响应用户的输入。用户必须非正常地结束程序。下面的例子解释了死锁是如何发生的。
线程1:调用函数来获取线程锁A(线程1:无线程锁,线程2:无线程锁)。
线程1:从获取线程锁的函数返回(线程1:持有线程锁A,线程2:无线程锁)。
切换到线程2:(线程1:持有线程锁A,线程2:无线程锁)。
线程2:调用函数来获取线程锁B(线程1:持有线程锁A,线程2:无线程锁)。
线程2:从获取线程锁的函数返回(线程1:持有线程锁A,线程2:持有线程锁B)。
线程2:调用函数来获取线程锁A(线程1:持有线程锁A,线程2:持有线程锁B)。
线程2:由于线程1持有线程锁A而被阻塞(线程1:持有线程锁A,线程2:持有线程锁B)。
切换到线程1:调用函数来获取线程锁B(线程1:持有线程锁A,线程2:持有线程锁B)。
线程1:调用函数来获取线程锁B(线程1:持有线程锁A,线程2:持有线程锁B)。
线程1:由于线程2持有线程锁A而被阻塞(线程1:持有线程锁A,线程2:持有线程锁B)。
与不对数据进行保护时产生的错误相似,由于程序运行的情况不同导致线程切换的时序不同,死锁错误间歇性地发生。例如,如果直到线程1持有线程锁A和B后才切换到线程2,那么线程1就可以完成工作而
LabWindowsCVI多线程技 相关文章:
- 频宽、取样速率及奈奎斯特定理(09-14)
- 为什么要进行信号调理?(09-30)
- IEEE802.16-2004 WiMAX物理层操作和测量(09-16)
- 为任意波形发生器增加价值(10-27)
- 基于PCI 总线的高速数据采集系统(09-30)
- 泰克全新VM6000视频测试仪助力数字电视等产品测试 (10-06)