# Perspective invoke asychronous code example

**URL:** <https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110>\
**Category:** Ignition\
**Tags:** perspective, vision, scripting\
**Created:** [August 22, 2025, 1:49pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110 "2025-08-22T13:49:48Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![pierre.declercq](https://avatars.discourse-cdn.com/v4/letter/p/3d9bf3/32.png) [@pierre.declercq](https://forum.inductiveautomation.com/u/pierre.declercq)\
**Post date:** [August 22, 2025, 1:49pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/1 "2025-08-22T13:49:48Z")

</div>

It's absolutely a shame that inductive automation doesn't document the invoke asychronous function more. Even in the documentation there is only a mini example for vision while the scope also extends to perspective. In short, it's a very important function with a minimum of information... I'm looking to execute code asynchronously and return it in the DOM, on a page, and even at the simplest just a result in a label and impossible to find how efficiently... Disappointed

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [August 22, 2025, 2:08pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/2 "2025-08-22T14:08:22Z")

</div>

> [@pierre.declercq](#):
>
> and return it in the DOM

All Ignition jython scripts run in the gateway, not in the browser. How do you expect to deliver any results to the DOM of a page?

Fundamentally, `system.util.invokeAsynchronous()` is just a convenience wrapper around Java's native `Thread` class. That's it. Asynchronous threads have **no connection** to Perspective pages.

Not that you cannot use an async thread to do heavy lifting, but you will need to use a message to push any results back into Perspective scope.

Note that Perspective does not expose the DOM, nor provide any tools to use javascript in the browser. There are kludges for certain cases, but to really do it requires a third party module (see @bmusson's kit).

---

<div class="post-metadata">

**Author:** ![pierre.declercq](https://avatars.discourse-cdn.com/v4/letter/p/3d9bf3/32.png) [@pierre.declercq](https://forum.inductiveautomation.com/u/pierre.declercq)\
**Post date:** [August 22, 2025, 2:21pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/3 "2025-08-22T14:21:56Z")

</div>

I take a markdown component to inject some js scripts but it is not the topic here.

“but you will need to use a message to push any results back into Perspective scope.”

→I try to use system.perspective.sendMessage(“text”) but nothing appear in the message event listener

I start with this trivial code

```python
def longProcess():
	val="test"
    system.perspective.sendMessage("text")
system.util.invokeAsynchronous(longProcess)

```

but i understant the send message into this thread cannot access to system.perspective so… how to? Regarding the documentation, the example use “event.source.parent” and “system.util.invokeLater(sendBack)” that are not part of perspective

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [August 22, 2025, 2:32pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/4 "2025-08-22T14:32:35Z")

</div>

Create local variables ahead of that `def` to capture session id and page id (via jython closure), and use them within the async function as parameters to `.sendMessage()` to explicitly target the origin session and page.

---

<div class="post-metadata">

**Author:** ![pierre.declercq](https://avatars.discourse-cdn.com/v4/letter/p/3d9bf3/32.png) [@pierre.declercq](https://forum.inductiveautomation.com/u/pierre.declercq)\
**Post date:** [August 22, 2025, 2:53pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/5 "2025-08-22T14:53:32Z")

</div>

my event handler listen on the “session”. when i click on a button i launch a script in “scripting” with the session id:

def runAction(self, event):  
sessionId = session.props.id  
async.longProcess(sessionId)

my script:

def longProcess(sessionId):  
sess=[sessionId]  
def sendBack():  
val=True  
system.util.sendMessage("right project name", "text", scope="session",clientSessionId=sess[0])  
system.util.invokeAsynchronous(sendBack,sess)

but nothing appear (my event handler just change label text property)

def onMessageReceived(self, payload):

# implement your handler here

self.props.text="hello"

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [August 22, 2025, 2:57pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/6 "2025-08-22T14:57:06Z")

</div>

Please reformat as code.

---

<div class="post-metadata">

**Author:** ![pierre.declercq](https://avatars.discourse-cdn.com/v4/letter/p/3d9bf3/32.png) [@pierre.declercq](https://forum.inductiveautomation.com/u/pierre.declercq)\
**Post date:** [August 22, 2025, 3:36pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/7 "2025-08-22T15:36:51Z")

</div>

i have a button, onClick event:

```python
def runAction(self, event):
	sessionId = session.props.id
	async.longProcess(sessionId)

```

on the scripting i have an async script:

```python
def longProcess(sessionId):
	sess=[sessionId]
	def sendBack(sess):
		system.util.sendMessage(project="Supervisory_System", messageHandler="gtwyMess", scope="CG",clientSessionId=sess[0])
		system.perspective.sendMessage(messageType="text",scope="session",sessionId=sess[0])
system.util.invokeAsynchronous(sendBack,sess)

```

I have tried gateway message "gtwyMess":

```python
def handleMessage(payload):
	system.perspective.sendMessage("text",scope="session")

```

i have a label with message handler “text”

```python
def onMessageReceived(self, payload):
	# implement your handler here
	self.props.text="hello"

```

But wont work. This trivial code is juste to understand how async can send back data of course.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [August 22, 2025, 3:45pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/8 "2025-08-22T15:45:57Z")

</div>

Change `def sendBack(sess):` to `def sendBack():`, then omit `sess` from `invokeAsynchronous()`. Spend some time learning how python **closures** work.

Don't bother with `system.util.sendMessage()`. Going through a gateway message handler doesn't help you, especially when the message handler's use of `system.perspective.sendMessage()` has no way to specify what Perspective session is involved. (And its `scope='S'` option can only deliver to session message handlers, not to component message handlers.)

---

<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 22, 2025, 3:46pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/9 "2025-08-22T15:46:39Z")

</div>

> [@pierre.declercq](#):
>
> But wont work.

Which part? What is your evidence it isn't working (e.g. are there errors in the logs)? Have you tried adding logging statements at various points to see where execution is being dropped?

> [@pierre.declercq](#):
>
> on the scripting i have an async script:
> 
> ```python
> def longProcess(sessionId):
> sess=[sessionId]
> def sendBack(sess):
> system.util.sendMessage(project="Supervisory_System", messageHandler="gtwyMess", scope="CG",clientSessionId=sess[0])
> system.perspective.sendMessage(messageType="text",scope="session",sessionId=sess[0])
> system.util.invokeAsynchronous(sendBack,sess)
> 
> ```

This doesn't make sense.  
Your action script has `async.longProcess`, implying you're attempting to call this project library function.

But in the project library, you're using `system.util.invokeAsynchronous`, but _outside_ of any context?

Try this minimal example:

# Project Library Script `async`

```python
import time

def longProcess(sessionId):
	time.sleep(5) # NEVER ACTUALLY DO THIS, THIS IS ONLY A DEMONSTRATION
	callback(sessionId)

def callback(sessionId):
	system.perspective.sendMessage(messageType="text", scope="session", sessionId=sessionId)

```

# Action Handler

```python
def runAction(self, event):
	sessionId = session.props.id
	# NOTE: You pass a **callable reference** to the project library function
	system.util.invokeAsynchronous(async.longProcess, args=[sessionId])

```

---

<div class="post-metadata">

**Author:** ![pierre.declercq](https://avatars.discourse-cdn.com/v4/letter/p/3d9bf3/32.png) [@pierre.declercq](https://forum.inductiveautomation.com/u/pierre.declercq)\
**Post date:** [August 22, 2025, 4:03pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/10 "2025-08-22T16:03:02Z")

</div>

> [@paul-griffith](#):
>
> this minimal example:
> 
> # Project Library Script `async`
> 
> ```python
> import time
> 
> def longProcess(sessionId):
> time.sleep(5) # NEVER ACTUALLY DO THIS, THIS IS ONLY A DEMONSTRATION
> callback(sessionId)
> 
> def callback(sessionId):
> system.perspective.sendMessage(messageType="text", scope="session", sessionId=sessionId)
> 
> ```
> 
> # Action Handler
> 
> ```python
> def runAction(self, event):
> sessionId = session.props.id
> # NOTE: You pass a **callable reference** to the project library function
> system.util.invokeAsynchronous(async.longProcess, args=[sessionId])
> 
> ```

I change

```python
sessionId = session.props.id

```

by

```python
sessionId = self.session.props.id

```

and the async function working.

Thanks for the sample code. I now can do some crazy things!!

---

<div class="post-metadata">

**Author:** ![Bushmatic](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bushmatic/32/87014_2.png) [@Bushmatic](https://forum.inductiveautomation.com/u/Bushmatic)\
**Post date:** [January 28, 2026, 11:29am UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/11 "2026-01-28T11:29:58Z")

</div>

Reviving an old thread with a potentially dumb question… What is the functional difference between the message handling method shown here versus simply ending the long running function with `return` and calling the library script as normal within `system.util.invokeAsynchronous`? My thought is the `sendMessage` method intends to pass the result(s) of the function around to different parts of the session without binding up a thread / the GUI?

---

<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:** [January 28, 2026, 4:45pm UTC](https://forum.inductiveautomation.com/t/perspective-invoke-asychronous-code-example/110110/12 "2026-01-28T16:45:41Z")

</div>

`invokeAsynchronous` returns a Java Thread object, and there's no easy way to get from that thread to the return value of the function.  
If you don't need to return to the GUI scope you started from, or you can indicate your results via some other global mechanism (e.g. writing to tags) then sure, you can do everything in your async thread.

But if you need to go back to the GUI scope you started in, you have to carry some context into the async thread and use it to go back.
