Best practice for time delay in script

I have a few tags/components that have a script on it using:

import time
time.sleep()

Would a better means be using:

import threading
threading.Event().wait()

or use:

system.util.invokeAsynchronous(function, [args], [kwargs], [description])```

Kinda hard to answer when we don't know what you use it for.

I'd first try to rework the whole thing so that it doesn't need to wait in the first place.

3 Likes

Ignition is an Event driven architecture? Why do you think you need to wait?

Are you saying that you have Tag Value Change scripts with sleep() in them?

That is a HUGE problem.

2 Likes

I think so. Im trying to find one so I can paste the code here and get peoples opinion.

What matters is not the code, but what you use it for.

1 Like

Any .sleep() or .wait() is bad in events. Events that don't have a dedicated thread should always run in a few milliseconds.

Delegating to an asynchronous thread and waiting there is reasonable for occasional cases. Perspective is tolerant of small sleeps in its events, as it adds threads dynamically. (But can explode into thousands of threads if misused.)

If you must perform many timed operations, you should:

  • Create state machines for each, and run them all from one timer event, or

  • Create your own persistent ThreadPoolExecutor, with a suitable number of threads, and use its various .schedule*() methods.

1 Like

Here is an example:

	import time
	if currentValue.value == 1:
		time.sleep(1)
		system.tag.writeBlocking("[~]Ignition_HandShake_Bit" , 0)

But why ?

Yeah, both the sleep and the writeBlocking are bad (writeBlocking on OPC tags can take many seconds if comms are busy).

That pattern looks buggy anyways. (self-reset?)

We have WinCC OPC connection thats bad about faulting out. So my WinCC guy just send me a 1 and I reset to a 0 every x amount of seconds.

That's terrible. A robust, sleep-less approach would be two tags. One incremented once per second by WinCC, the other incremented once per second by Ignition (or echoing the WinCC value). With some rollover limit. Could even be just the clock second. Writing tags from two directions in handshakes is horrible and buggy.

(Or once per x seconds, whatever.)

Needing to use .sleep() is a "code smell" that suggests that your algorithm is flawed.

4 Likes

Here is an second example using the sleep function on a Button:
I have made a momentary button in perspective. Bu when operator clicks the button shortly the event is missed in the PLC. Therefore I have extend the mouse button click by using a sleep timer. When an operator clicks on the button the tag will be at least 2 seconds TRUE

def runAction(self, event):
	import time
#	This function writes an 1 for 2 second to tag
	tag = self.view.params.TagPath
	bool_value='true'
	system.tag.writeBlocking([tag],bool_value)
	time.sleep(2)
	bool_value='False'
	system.tag.writeAsync([tag],bool_value)

Don't do this. It cannot be made reliable. For what you describe, simply set the boolean TRUE and let the PLC reset it when it sees it. (Fire and forget is one of the few cases where writing a tag from two directions makes sense.)