# Perspective views and long running scripts

**URL:** <https://forum.inductiveautomation.com/t/perspective-views-and-long-running-scripts/116815>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [August 18, 2026, 10:23am UTC](https://forum.inductiveautomation.com/t/perspective-views-and-long-running-scripts/116815 "2026-08-18T10:23:45Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![pgmo](https://avatars.discourse-cdn.com/v4/letter/p/d07c76/32.png) [@pgmo](https://forum.inductiveautomation.com/u/pgmo)\
**Post date:** [August 18, 2026, 10:23am UTC](https://forum.inductiveautomation.com/t/perspective-views-and-long-running-scripts/116815/1 "2026-08-18T10:23:45Z")

</div>

As far as I understand, Python scripts run on the gateway. Suppose a button in a Perspective view starts a long running script, after which I have to update a property of the view: since the Python script runs on the gateway, my UI experience is fluid, even while that script is running. What's then the purpose of a `system.util.invokeAsynchronous`and `system.util.invokeLater` calls in that case? What should I care of, when a button starts a long running script in a Perspective view?

Thanks in advance, regards

---

<div class="post-metadata">

**Author:** ![bobby.miller](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bobby.miller/32/85153_2.png) [@bobby.miller](https://forum.inductiveautomation.com/u/bobby.miller)\
**Post date:** [August 18, 2026, 10:50am UTC](https://forum.inductiveautomation.com/t/perspective-views-and-long-running-scripts/116815/2 "2026-08-18T10:50:11Z")

</div>

> [@pgmo](#):
>
> system.util.invokeLater

This has no purpose outside of vision.

> [@pgmo](#):
>
> system.util.invokeAsynchronous

This will return the event handler immediately and move the work to another thread. This prevents the sessions's scripting request being held open. So if you have a script doing a bunch of things, and you want to spin off one part of the thing while letting the rest of the things finish, you'd use this.

This adds complexity, though, because if you have a button smasher (like myself, I super smash bros UI buttons), you have to add protections to keep the calls from stacking up. Something like:

```python
if self.custom.busy:
    return

self.custom.busy = True
component = self
logger = system.util.getLogger("myProject")

def work():
    try:
        component.custom.result = do_the_slow_operation()
    except:
        logger.exception("Long operation failed")
    finally:
        component.custom.busy = False

system.util.invokeAsynchronous(
    work,
    description="Long Perspective operation"
)

```

---

<div class="post-metadata">

**Author:** ![bschroeder](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bschroeder/32/13260_2.png) [@bschroeder](https://forum.inductiveautomation.com/u/bschroeder)\
**Post date:** [August 18, 2026, 11:32am UTC](https://forum.inductiveautomation.com/t/perspective-views-and-long-running-scripts/116815/3 "2026-08-18T11:32:53Z")

</div>

Are you wanting to return something from that button action? Do you want the UI to show that things are working while the activity is going on?

The way I would handle something like this would be to call the function from the button, and then if you need to return data, use [system.perspective.sendMessage | Ignition User Manual](https://docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-perspective/system-perspective-sendMessage) to return the data back.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [August 18, 2026, 5:06pm UTC](https://forum.inductiveautomation.com/t/perspective-views-and-long-running-scripts/116815/4 "2026-08-18T17:06:48Z")

</div>

`system.util.invokeAsynchronous` is also available **everywhere** on the gateway. It's extremely relevant to, say, a tag event script, to be able to move an expensive script off the extremely limited queue (as long as it's done carefully).

It's also generally a useful tool, programmatically, to be able to say "continue working on this task while my primary execution continues".
