I have developped a vision application that visualises production data using multiple named queries. The application works so fine, except that sometimes it freezes (not responding) for a couple of seconds.
In the diagnostic I found this entry many times : "Non-responsive UI thread detected. Stack saved at ..."
When I open the stack, I couldn't really identify where the issue exactly is .. if anyone can help.
The very first thread in that dump is running a named query from a custom component method (updateDailyTrefilage). Which is running from a property change event. That event runs in the foreground thread, and any delays will freeze the UI.
Run your named queries from named query bindings.
If you absolutely have to use scripts, learn to use system.util.invokeAsynchronous safely.
In fact I have built my whole application on running multiple named queries on a script fired upon a property change .. which makes sense to the unresponsive UI thread issue I have.
The problem now is that I am doing further complex calculation (production KPIs, ratios ...) in my script upon the queries results ... which will be difficult to do on binding directly ... I guess now I have to review the whole building of my project.
Scripts are automatically invoked on the EDT for thread safety when interacting with Swing, but you can always do your own heavyweight processing in an asynchronous thread and move back to the EDT yourself. That's the entire raison d'etre of the system.util.invokeAsynchronous function Phil mentioned.
Basically:
On EDT, user triggers your script by some action
On EDT, script gathers whatever state it needs from the GUI, including enough information to 'call back' when the computation is done
Script passes that state in as arguments to a dedicated function (ideally in your project library) that will run asynchronously
Once the script logic is complete (or at various checkpoints to report progress) script uses system.util.invokeLater to push callbacks on to the EDT.
I'd be honest to say that I was suspecting my need for an asynchronous call method, but I am not used to multithreading in general (and in ignition in particular) so it is kind of a big topic to me.
My problem was solved by simply using an system.util.invokeAsynchronous .. literally this little change made my application works without problem .. Even more, my application is now running more smoothly as the updates are taking place gradually as the script executes (not like before where the screen was freezed until all components are updated at once).
For the record, and to help further users who will stumble across the same problem, I made a short comparison diagram :
The diagram is BROKEN. You cannot update the UI components from that background thread. It may appear to work, but will intermittently crash your Vision client. Go back and re-read the old topic I linked. And property access (read or write) or method calls on components must occur on the UI thread. Use invokeLater to fire off such actions.
Refactor your custom methods for "heavyweight calculations" to the script library, and then you can call them as needed from whatever function was invoked asynchronously. Any swing component property values that are needed for the calculation must be packaged up and delivered to the asynchronous function as arguments via the invokeAsynchronous call. Use a nested callback function that can supply the return values to the EDT via invokeLater. It is safe to deliver a swing component as an argument to an asynchronous function and pass it around, and this is sometimes necessary for getting return values to the desired place, but do not touch any of the component's properties or methods outside of a callback function that is called using invokeLater.