Does the Tag Change Event work with a queue?

Hi!

I understand that the tag change detects all the events that change and saves them in a queue. Then every time the script executes, the next update waits for the script to finish and then the other execute.

Wanna know if this work like that and if there is any way of cleaning that queue.

Context: My code has an event tag change that looks at some tags. Some of them can change independently but others could or could not change at the same time really fast. However, my script has a time.sleep(1) so if a lot of changes happend fast the code picks the last "stable" state. The things is even that the code wait and gets the correct state it gets execute 4 or 5 more times because of those fast updates, that's why I wanna remove those fast updates.

No, you can't clear it, and you definitely should not be sleeping, blocking, or doing anything in general that executes slowly in your tag change event scripts - there is a shared thread pool responsible for executing these scripts and you will be blocking other tag change event scripts from executing in a timely manner.

Are you telling me that if I do time.sleep(1000) in a lot of those script I could block all the tag change event? (not doing simply exaggerating the problem)

What If instead of calling directly a script I use system.util.invokeAsynchronous(). Could that work?

Yes, you really shouldn't do this.

Yes, but now you risk creating many threads, and it's probably not the right answer.

You need to rethink what you're doing so that it doesn't involve sleeping or ordering between tags if possible.

4 Likes

I'll do it.
Thanks Kevin!

We thought about it.

We can't call the script directly to not overload the tag events threads.
Our aproach is to use system.util.invokeAsynchronous with a lock.

The first call is going to lock the thread, because the lock is used globally. Whenever another tag changes it's simply going to encounter the lock locked and exit the thread.

A simplified version:

# [tag event change]
system.util.invokeAsynchronous(path.to.function.main)
# [script]
import threading

def main():
	lock = global.Lock()  # over simplified

	# if lock.locked():
	# 	return

	# lock.acquire()  # we lock it

	if not lock.acquire(False):  # @pturmel solution
		return

	# code to execute
	print "Hello world!"

	return

Even if we have more that one thread waiting at the lock.locked() the code won't break. And because we have a 1 second delay we can easily not have multiples thread waiting to be executed.

Just posted to add to the forum. It's currently working fine ^^

That is racy. You can get two threads executing the latter .acquire(). You should use this construct:

	if not lock.acquire(False):
		return

That should be followed by a try: - finally: block to ensure the lock is released in spite of any errors.

2 Likes