# \[BUG-5802\]Async Tag Event Script loses reference paths

**URL:** <https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768>\
**Category:** Ignition\
**Tags:** scripting\
**Created:** [March 29, 2022, 6:16pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768 "2022-03-29T18:16:25Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [March 29, 2022, 6:16pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/1 "2022-03-29T18:16:26Z")

</div>

I have a system that is firing off a ton of tag event scripts, but uses a singleton to manage their threads, and so because of this I need to execute my tag event scripts asynchronously.

In my case, I am using threading instead of `invokeAsynchronous`, but the issue persists either way

When I try to use tag paths in asynchronous scope, it loses the ability to use a reference path. I am assuming because I am passing the script outside of some scope and not realizing it, or something under the hood with how the tag read and write scripts handle tag paths when there is a tag event in their stack trace. Totally guessing here

Any ideas how to get this to work? Long story short, I cannot know what tag path I will need before the async function, I have to determine that dynamically inside the async function as part of a config file.

Essentially this is the script:

```auto
# This will print the value of the second tag
system.util.getLogger("Example").info(str(system.tag.readBlocking(["[.]Second Tag"])[0].value))
def writeFunc():
	# This will print None
	system.util.getLogger("Example").info(str(system.tag.readBlocking(["[.]Second Tag"])[0].value))

# The stock ignition way
system.util.invokeAsynchronous(writeFunc)

# Essentially How I am doing this in threading:
# import threading
# new_thread = threading.Thread(target=writeFunc)
# new_thread.start()

```

---

<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:** [March 29, 2022, 6:21pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/2 "2022-03-29T18:21:54Z")

</div>

You’re going to have to figure out an approach that allows you to derive the full tag path before asynchronous execution begins.

The event scripts execute with information about the default tag provider and relative path (parent path) stored in Java ThreadLocals. This information is lost once you’ve jumped to another thread.

---

<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:** [March 29, 2022, 6:24pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/3 "2022-03-29T18:24:39Z")

</div>

I think you might be able to extract what you want from the current thread, then set it in the new thread via `ScriptContext`: [ScriptContext](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.15/com/inductiveautomation/ignition/common/script/ScriptContext.html)

---

<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:** [March 29, 2022, 6:24pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/4 "2022-03-29T18:24:46Z")

</div>

Ah, but maybe you could store those and set them yourself (danger…)…

`ScriptContext` is `com.inductiveautomation.ignition.common.script.ScriptContext`.

Before invokeAsync, store the relative path:

```auto
relative_path = ScriptContext.relativeTagPathRoot()

```

first thing inside the async func:

```auto
ScriptContext.setRelativeTagPathRoot(relative_path)

```

---

<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:** [March 29, 2022, 6:41pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/5 "2022-03-29T18:41:28Z")

</div>

Ooooo! Neat. I wondered where you tucked some of this stuff.

---

<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:** [March 29, 2022, 6:45pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/6 "2022-03-29T18:45:55Z")

</div>

We’re gonna start passing the ScriptContext values into the thread started by invokeAsync, but you’ll have to keep doing it manually for your own custom threads.

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [March 29, 2022, 6:49pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/7 "2022-03-29T18:49:02Z")

</div>

This is exactly what I needed, this singleton method is explicitly being called from tag event scripts in this case, so I should always have access to that stuff before the async call.

Script for anyone in the future:

```auto
from com.inductiveautomation.ignition.common.script import ScriptContext

relative_path = ScriptContext.relativeTagPathRoot()

system.util.getLogger("Example").info(str(system.tag.readBlocking(["[.]SiblingTag"])[0].value))
def writeFunc():
	ScriptContext.setRelativeTagPathRoot(relative_path)
	system.util.getLogger("Example").info(str(system.tag.readBlocking(["[.]SiblingTag"])[0].value))

system.util.invokeAsynchronous(writeFunc)

# If you would prefer threading instead of invokeAsync
# import threading
# new_thread = threading.Thread(target=writeFunc)
# new_thread.start()

```

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [March 29, 2022, 6:50pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/8 "2022-03-29T18:50:22Z")

</div>

> [@Kevin.Herron](#):
>
> but you’ll have to keep doing it manually for your own custom threads.

Outside off you guys setting this inside `invokeAsync`, are there any other special reasons that we should be using `invokeAsync` instead of `threading`?

We are using threading so that our code is test compatible with `pytest` in python 2.7. But if there are strong reasons to use the first party function, I am not opposed to switching.

---

<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:** [March 29, 2022, 6:51pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/9 "2022-03-29T18:51:08Z")

</div>

I wouldn’t use `threading` because I trust approximately nothing that comes from the Jython stdlib.

---

<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:** [March 29, 2022, 6:56pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/10 "2022-03-29T18:56:38Z")

</div>

`invokeAsync` also allows you to pass a description of your async thread, which can be useful for diagnosis. You could probably monkey-patch `threading` to do the same, but at that point, why bother?

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [March 29, 2022, 6:58pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/11 "2022-03-29T18:58:16Z")

</div>

In this case we are storing the thread in a `WeakKeyDictionary `, I would suppose we could just do the same with the thread provided by `invokeAsync`.

Is it possible to not immediately start the thread with `invokeAsync`?

> [@paul-griffith](#):
>
> `invokeAsync` also allows you to pass a description of your async thread, which can be useful for diagnosis.

Ooh good call, didnt see that!

---

<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:** [March 29, 2022, 7:00pm UTC](https://forum.inductiveautomation.com/t/bug-5802-async-tag-event-script-loses-reference-paths/57768/12 "2022-03-29T19:00:28Z")

</div>

`invokeAsync` is just `java.lang.Thread` and `java.lang.Runnable`, with a description set on the `ScriptContext`.

You can use those directly, and start the thread whenever you’d like.
