Root container script triggers only once

Hello,

I need to fix a Vision V 8.1.17 app that I didn't write.

problem : a script with invokeAsynchronous triggers the root container only once.

On a view, a button triggers this script (XXX can take some seconds to end) :

[...]
def longProcess(rootContainer = event.source.parent.parent):
   import system
     results = XXX()

   def sendBack(results = results, rootContainer = rootContainer):
      rootContainer.resultsProperty = results
      
   system.util.invokeLater(sendBack)
  
system.util.invokeAsynchronous(longProcess)

the root container starts with

[...]
print 'inside RC !'
if event.propertyName == "resultsProperty":	
    blabla

At the first execution, the script works normally.
( "inside RC!" is printed in the log and blabla is well executed)
Then the root container script is no longer executed !
("inside RC!" no longer appears).

if I change views, then the script works again, again only once.

Someone to help me ?

Thanks !

Where "exactly" is this script on the button?

Are you testing this in the designer or in an actual client? That can make a difference.

The fact that `print 'inside RC !' is only printing once, makes me feel like there is more context to these scripts then what your showing, as if that line was really the top line a property change script of the Root Container, you would definitely have it printed more than once.

The button is on the container:
HOME (with startup script)
__Root container (with script)
____container
______the button (so with script)

The problem occurs in preview mode as well as with client.

Yes, the line 'inside RC!' is printing more that once.
eg :

First run:

14:24:07.941 [AWT-EventQueue-0] INFO vision.App - Starting Up..
inside RC !resultsProperty
inside RC !qualityList
inside RC !dataQuality
inside RC !background$Quality
inside RC !componentRunning
[...] blabla  (print out of the function longProcess)
inside RC !resultsProperty
-> execution ok

But, on the next try 'inside RC!' is never printed, as long as I stay on the same window.

In the root container, there is a try except section.
if ok then it does a system.nav.swapWindow
if except then it only does
event.source.getComponent('Container').getComponent('errorMsg').visible= 1

Okay, I threw together a quick test in my environment to try and replicate and was unable to replicate what you're seeing.

If you can't post the actual code then I would suggest you call into support, as it would appear that the issue is somewhere inside of one of the scripts. I'm not sure how much we're going to be able to help you without more information.

Window structure:
image

Property Change script on RootContainer:

if event.propertyName == 'resultsProperty':
    print 'execute blabla'

Action performed script on button:

def xxx():
    processStart = system.date.now()
    count = 0
    seconds = 2
    while system.date.isBetween(system.date.now(),processStart,system.date.addSeconds(processStart,seconds):
        count += 1
    return str(count)

def longProcess(rootContainer = event.source.parent.parent):
    results = xxx()

    def sendBack(results = results,rootContainer = rootContainer):
        rootContainer.resultsProperty = results

    system.util.invokeLater(sendBack)

system.util.invokeAsynchronous(longProcess)

async

2 Likes

Here the begining of root container script :

import java.lang.Exception
from java.sql import SQLException
from MES.VARIABLES_GLOBALES import *
import ast
print 'inside RC !' + event.propertyName


if event.propertyName == "resultsProperty":	
[..]

Here is an complet example of script for the button

import java.lang.Exception
from java.sql import SQLException
from MES.VARIABLES_GLOBALES import *
import ast


event.source.parent.getComponent('errorMsg').visible = 0	# on masque le messssage d'erreur de scan
event.source.componentEnabled = False		# SB pendant la lecture, on neutralise le bouton

event.source.scanEnCours = True								# on active 'scan en cours..." sur le bouton

print 'Debut script clic ' + str(system.date.now())

def longProcess(rootContainer = event.source.parent.parent):
   import system
 
   print 'avant readTagdata ' + str(system.date.now())
   results={'ERREUR': 'Message non conforme : '}
   print ' apres readTagdata ' + str(system.date.now())

   def sendBack(results = results, rootContainer = rootContainer):
      rootContainer.resultsProperty = results
      print '3 apres rp=Res ' + str(system.date.now())

      
   system.util.invokeLater(sendBack)

print '4 apres invokelater ' + str(system.date.now()) 
system.util.invokeAsynchronous(longProcess) 
print 'FIN traitement clic ' + str(system.date.now())

log:

Debut script clic Mon Aug 21 15:36:21 CEST 2023
avant readTagdata Mon Aug 21 15:36:21 CEST 2023
 apres readTagdata Mon Aug 21 15:36:21 CEST 2023
3 apres rp=Res Mon Aug 21 15:36:21 CEST 2023
inside RC !resultsProperty
resultsProperty non vide{'ERREUR': 'Message non conforme : '}
dicoRFid_API = tagResult	{'ERREUR': 'Message non conforme : '}
Dan TRY RC Home
Dans Exept ! du RC

log for next try :

Debut script clic Mon Aug 21 15:37:00 CEST 2023
avant readTagdata Mon Aug 21 15:37:00 CEST 2023
 apres readTagdata Mon Aug 21 15:37:00 CEST 2023
3 apres rp=Res Mon Aug 21 15:37:00 CEST 2023

results={'ERREUR': 'Message non conforme : '}

This never changes, why would the property change event fire if the property isn't changing?

You can see in your second try, that the line printed after you "set" the property is executing.

2 Likes

It is for this test only.

but maybe you gave me the solution : the property don't change with the real command
(when pb occurs).
I have to force it to change after the first exec

If the property changes, then the property change script will fire, if it doesn't, then it won't.

If I alter my test to return a constant value, it only fires once, just as you are seeing.

yes thanks !

I have to found how change event.propertyName after the first try.
I don't know if it's the good way but it's working :

I add a line event.source.parent.parent.resultsProperty=0 at the beginning of lingProcess:

def longProcess(rootContainer = event.source.parent.parent):
   import system
   # Do something here with the database that takes a long time.
   
   event.source.parent.parent.resultsProperty=0
[...]

Thanks for you help, I spent hours for this problem !!
(I begin in Ignition script so it's not very easy for me.)

It is not. You are writing to a Swing property from a background thread. This can randomly crash your Vision client.

Move it to the button script, at some point before the invokeAsynchronous().

1 Like

yes thanks, I did that.
Works fine !