In summary, my question is:
What is best practices, and what to avoid when writing Tag Event Scripts?
Background and more details regarding question:
From what I have read, the Tag Event Scripts are running in fixed size thread pool (default 3 threads). This would mean that if you have multiple Tag Event Scripts that does slow/blocking operations, it could block any other tag event scripts from running.
This would presumably mean that running e.g. network calls like OPC calls, or other potentially time consuming calls from these scripts risky.
But what about performing reads and writes to the tag system?
I would assume that you should in that case prefer async version, to reduce risk of potential lockup. I note that in the script examples in Tag Event Scripts | Ignition User Manual is actually using blocking version. Furthermore Kevin writes that you should be careful with async invocations in
Tag Event Scripts, ref. Tag Event Scripting Performance - #5 by Kevin.Herron . He was talking about system.util.invokeAsynchronous()
but presumably we could extrapolate the same to apply to the async version of tag read/write.
The reason my attention was drawn to this, was due to noticing some issues where the gateway could get locked up when tag was restarting (got some blank entries stuck in "running scripts", there the elapsed time just kept counting and counting). Digging into this, I found some code that had been written to dynamically enable/disable parts of a tag based on value from PLC. This is also using the depreciated system.tag.write
and read
, so that may also play into this.
But before I start rewriting these, and other scripts, I would like to try and collect some information on what is best practice when it comes to Tag Event Scripts.
For reference, one of the scripts in question, running on a derived tag with an integer describing number of packs:
def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
val = currentValue.getValue()
for i in range(1, 33):
packPath = str(tagPath).replace("Battery/inNumberOfPacks","Pack{:02d}".format(i))
packNumber = system.tag.read(packPath + "/Parameters.PackNumber").value
if val >= packNumber:
system.tag.write(packPath + ".Enabled", 1)
else:
system.tag.write(packPath + ".Enabled", 0)