# Ignition 8 invokeLater function doesn't seem to exist

**URL:** <https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174>\
**Category:** Ignition\
**Tags:** ignition80\
**Created:** [May 21, 2019, 1:08am UTC](https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174 "2019-05-21T01:08:00Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![roger\_larson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/roger_larson/32/8574_2.png) [@roger\_larson](https://forum.inductiveautomation.com/u/roger_larson)\
**Post date:** [May 21, 2019, 1:08am UTC](https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174/1 "2019-05-21T01:08:00Z")

</div>

Hi all,

Is there a problem with system.util.invokeLater? I keep getting this error even though my function runs fine with system.util.invokeAsynchronous. I was using 8.0.1 and then transferred over to an 8.0.2 rc from this past Friday.

I seem to be able to call it from the script console, and I feel like I have called it in vision before, but it fails in perspective (for reference, it is called on a property change script, but is located on a component’s script area).

Error message:

```auto
|SystemUtilities|20May2019 17:40:03|Error running function from system.util.invokeAsynchronous|
| --- | --- | --- |
|com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 47, in doAsynch AttributeError: 'com.inductiveautomation.ignition.common.script.Imm' object has no attribute 'invokeLater'
at org.python.core.Py.AttributeError(Py.java:207)
at org.python.core.PyObject.noAttributeError(PyObject.java:1032)
at org.python.core.PyObject. __getattr__ (PyObject.java:1027)
at org.python.pycode._pyx32.doAsynch$2(:47)
at org.python.pycode._pyx32.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:171)
at org.python.core.PyBaseCode.call(PyBaseCode.java:308)
at org.python.core.PyFunction.function ___call__ (PyFunction.java:471)
at org.python.core.PyFunction. __call__ (PyFunction.java:466)
at org.python.core.PyFunction. __call__ (PyFunction.java:456)
at org.python.core.PyFunction. __call__ (PyFunction.java:451)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:776)
at com.inductiveautomation.ignition.gateway.script.GatewaySystemUtilities.lambda$_invokeAsyncImpl$0(GatewaySystemUtilities.java:62)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.python.core.PyException: Traceback (most recent call last): File "", line 47, in doAsynch AttributeError: 'com.inductiveautomation.ignition.common.script.Imm' object has no attribute 'invokeLater'
... 14 common frames omitted|

```

Sample script:

```auto
    loadingLabel = self.parent.getChild("Options").getChild("Loading Label")
	loadingLabel.props.text = "Loading Table..."
	def doAsynch(site = site, deviceType = deviceType, loadingLabel = loadingLabel):
		devices = shared.device.getDevices(site, deviceType)
				
		deviceNames = devices["deviceNames"]
		devicePaths = devices["devicePaths"]
		
		deviceNames, devicePaths = shared.util.naturalSortLists(0, deviceNames, devicePaths)
		
		data = []
		headers = ["Device", "Device Path"]
		for index, devicePath in enumerate(devicePaths):
			deviceName = deviceNames[index]
			devicePath = devicePaths[index]
			tags = shared.device.getTags(devicePath)
			
			tagNames = tags["tagNames"]
			tagPaths = tags["tagPaths"]
			tagNames = [tagName for tagName in tagNames if "SCADA" not in tagName]
			tagPaths = [tagPath for tagPath in tagPaths if "SCADA" not in tagPath]
			
			for tagIndex in range(len(tagPaths)):
				tagPath = tagPaths[tagIndex]
				tagName = tagNames[tagIndex]
				if tagName not in headers:
					headers.append(tagName)
		
		data = []
		for index, devicePath in enumerate(devicePaths):
			data.append({})
			for headerIndex, header in enumerate(headers):
				if headerIndex == 0:
					data[index][header] = deviceNames[index]
				elif headerIndex == 1:
					data[index][header] = devicePaths[index]
				else:
					data[index][header] = None
		
		def doLater(component = self, loadingLabel = loadingLabel):
			loadingLabel.props.text = ""
			component.props.data = data
			#component.makeColumnAttributes()
			component.readData()
		system.util.invokeLater(doLater)
	
	system.util.invokeAsynchronous(doAsynch)

```

Any ideas? I don’t think it is scoping. Maybe something in my code is interfering with invokeLater? Or is this function removed?

Cheers,  
Roger

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [May 21, 2019, 1:11am UTC](https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174/2 "2019-05-21T01:11:19Z")

</div>

`invokeLater` is a concept that only makes sense in Vision - it posts a chunk of code to run later on the Event Dispatch Thread, which is a Java Swing thing.

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [May 21, 2019, 1:22am UTC](https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174/3 "2019-05-21T01:22:37Z")

</div>

I don’t know if there’s an analog you’re supposed to use in Perspective or not. Someone more familiar will have to answer tomorrow.

---

<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:** [May 21, 2019, 12:51pm UTC](https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174/4 "2019-05-21T12:51:26Z")

</div>

I’ve updated [later.py](https://www.automation-pros.com/ignition/later.py) for Ignition v8. It includes an implementation of invokeLater usable in gateway scope.

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [May 21, 2019, 2:12pm UTC](https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174/5 "2019-05-21T14:12:16Z")

</div>

There isn’t any perspective analog for invokeLater that I’m aware of, but I’m struggling to think of a use-case in perspective that can’t be done some other way.

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [May 21, 2019, 3:06pm UTC](https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174/6 "2019-05-21T15:06:39Z")

</div>

This pattern isn’t necessary in Perspective; you can interact with the session or component from the other thread without the invokeLater part.

---

<div class="post-metadata">

**Author:** ![roger\_larson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/roger_larson/32/8574_2.png) [@roger\_larson](https://forum.inductiveautomation.com/u/roger_larson)\
**Post date:** [May 21, 2019, 3:50pm UTC](https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174/7 "2019-05-21T15:50:48Z")

</div>

> [@cmallonee](#):
>
> There isn’t any perspective analog for invokeLater that I’m aware of, but I’m struggling to think of a use-case in perspective that can’t be done some other way.

> [@Kevin.Herron](#):
>
> This pattern isn’t necessary in Perspective; you can interact with the session or component from the other thread without the invokeLater part.

This makes sense. So we should be able to just write back to UI components without needing invokeLater then?

The main reason i'm asking is because we had a template in vision that had a script with this combination and upon modifying it to work on a perspective view, the invokeLater part failed to function. If we don't need it, that makes life easier.

And indeed, removing it makes the script work as intended!

Cheers,  
Roger

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [May 21, 2019, 4:06pm UTC](https://forum.inductiveautomation.com/t/ignition-8-invokelater-function-doesnt-seem-to-exist/25174/8 "2019-05-21T16:06:00Z")

</div>

You shouldn’t need `system.util.invokeLater()` in Perspective, but I would recommend a different approach to the doLater portion of the script: use `system.perspective.sendMessage()`.

If you haven’t already encountered it, you’ll find that scripts like this which rely on hard-coded component paths will begin to fail as you iterate through development, because you’ll probably be renaming components and restructuring Views. Use of the sendMessage method will allow you to bypass script failures which would be caused by component paths no longer resolving. in your use-case, instead of the `invokeLater()` call, use

```auto
self.props.data = data
system.perspective.sendMessage(
    messageType='UPDATELOADINGLABEL',
    payload={'text':''},
    scope='view')

```

and then attach a message handler to the Loading Label component (set the Message Type to ‘UPDATELOADINGLABEL’, and make sure you set the scope to ‘view’):

```auto
self.props.text = payload['text']

```

You can also use this same call at the beginning of your script to set the initial text of the component to be “Loading Table…”.
