multithreading - Delphi OmniThreadLibrary + OPC 客户端

标签 multithreading delphi opc

我正在使用单线程 OPC 客户端程序管理 3 个不同的西门子 PLC,这些 PLC 连接到同一个 OPC 服务器(同样由西门子提供)。

单线程客户端如下所示:

loop
 begin
  processPLC1;
  processPLC2;
  processPLC3;
end;

每个processPLC程序都会调用底层OPC库,例如:

 OPCutils.WriteOPCGroupItemValue(FGroupIf, FHandleItemOpc, Value);

好吧,现在我想在不同的线程中调用每个processPLC并并行工作。

我做了一些研究并使用 OmniThreadLibrary 开始了一些代码,但我不认为 OPC 代码是多线程安全的。是吗?

我应该使用task.Invoke或类似的东西吗? 返回 PLC 变量值的 ReadOPC 函数怎么样? 这里的最佳实践是什么?

谢谢!!!

最佳答案

我通常看到这通过两种方式完成:

1) 应用程序有一个由单个线程拥有的单个 OPC 客户端实例。然后,在读取/写入 OPC 值时,由客户端应用程序自动化的所有并行进程都会使用某种消息传递或与拥有 OPC 客户端的线程同步。

2) 每个线程拥有自己的私有(private)OPC客户端,每个线程独立地与OPC服务器通信。

就我个人而言,我发现最常用的方案是前者;一个 OPC(或其他专有)客户端对象,其中线程对客户端进行同步调用。实际上,在几乎所有流程控制情况下,您使用多线程的目的都是为了优雅地封装逻辑现实世界任务并将其与 UI 分离,而不是为了任何性能。这些线程可以阻塞相对“长”的时间来等待数据——如果需要的话,PLC 会很高兴地坚守一百毫秒。

您选择哪一个很大程度上取决于您的应用程序的规模和性质。对于花费很长时间等待外部实时事件的大量轻量级线程来说,在应用程序中保留单个 OPC 客户端实例并节省大量独立连接的开销是有意义的。对于少量繁重、快速移动的 OPC 密集型线程,为每个线程提供自己的 OPC 客户端也许是有意义的。

还要记住 OPC 标签的刷新率 - 很多时候服务器仅每隔约 100 毫秒左右更新一次它们。即使仅执行一次扫描,您的 PLC 也可能需要至少 10 毫秒。当数据永远不会那么快刷新时,让大量线程每秒独立轮询服务器一百次是没有意义的。

对于过程控制软件,您真正想要的是拥有大量空闲或低负载的 CPU 时间 - 线程越轻越好。总体系统响应能力是关键,并且让您的软件处理高负载情况的能力(突然大量任务集中在一起,而操作系统决定是时候索引 HDD...可以说,净空空间使齿轮保持润滑)。大多数线程可能大部分时间都在等待。事件和回调通常在这里最有意义。

此外,考虑 PLC 编程在这里也很重要。例如,在我的机器中,我有一些对时间要求非常严格的操作,同时它们每次运行时都有唯一的计时 - 这些过程的持续时间约为分钟,计时不到十分之一。每秒或更长时间,每天重复数百到数千次,并且每次运行时都有一个关键但不同的持续时间。我见过这些处理方式有两种 - 一种通过软件,一种通过 PLC。对于前一种情况,软件告诉 PLC 何时启动,然后继续运行,直到软件告诉它停止。这有明显的陷阱;在这种情况下,最好将时间间隔发送到 PLC 并让它进行计时。突然间,所有时间/轮询压力都从软件中消失,该过程可以优雅地处理诸如自动化计算机崩溃等问题。如果您想对 OPC 服务器施加沉重压力以获取时间关键数据,那么通常值得这样做重新评估整个系统的设计——软件和PLC。

关于multithreading - Delphi OmniThreadLibrary + OPC 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18040338/

相关文章:

delphi - 将 Indy 10 IdHTTP 与 TLS 1.2 结合使用

Java连接到OPC服务器: NotConnectedException (AutoReconnectController)

PLC 未连接到 KEP 服务器 (OPC)

linux - 从后台工作线程修改 Qt GUI

iphone - NSOperation 中的 NSURLConnection 同步方法

delphi - Indy,如何知道所需缓冲区的大小?

plc - 是否需要使用 OPC 服务器与 Controllogix 通信?

c# 线程和等待表单

python - 何时、为何以及如何在 Python 中调用 thread.join()?

delphi - 使用新 TADOQuery 的最有效方式(最快且最便宜)