# system.util.invokeAsynchronous threading details

**URL:** <https://forum.inductiveautomation.com/t/system-util-invokeasynchronous-threading-details/91221>\
**Category:** Ignition\
**Tags:** ignition81, scripting\
**Created:** [May 31, 2024, 7:30pm UTC](https://forum.inductiveautomation.com/t/system-util-invokeasynchronous-threading-details/91221 "2024-05-31T19:30:19Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![keenern](https://avatars.discourse-cdn.com/v4/letter/k/779978/32.png) [@keenern](https://forum.inductiveautomation.com/u/keenern)\
**Post date:** [May 31, 2024, 7:30pm UTC](https://forum.inductiveautomation.com/t/system-util-invokeasynchronous-threading-details/91221/1 "2024-05-31T19:30:20Z")

</div>

Hello,  
I have got some process that creates up to 200 threads. (Managed by some other scripts and verified) this has worked to speed up these data processing.

My question is does invokeAsynchronous truly allow use of multiple cores or is it only using user controlled multi processing. A single one of the threads takes about 200 ms to complete. But sometime I see the threads total times increase as we process each thread in order. (Start at 200ms and then increase each thread following but not always by the total 200 ms)

The root of my question is what is the limit then? how many cores I have or the way in which the threads are handled for multi processing. Does it truly get access to run in all cores or only on a subset of the cores? Or even worse only access to one core as in the user defined abstraction of threading.

This is very technical heavy and more trying to understand how ignition works which scheduling threads.

---

<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 31, 2024, 7:33pm UTC](https://forum.inductiveautomation.com/t/system-util-invokeasynchronous-threading-details/91221/2 "2024-05-31T19:33:43Z")

</div>

> [@keenern](#):
>
> truly allow use of multiple cores

Yes.

But whatever your algorithm does, especially if there are shared variables, can cause bottlenecks. Also, a common mistake is to include the parentheses for the background function when calling `system.util.invokeAsynchronous()`. That causes the background function to run right then, and usually nothing is put in the background.

Show your code for more detailed assistance.

---

<div class="post-metadata">

**Author:** ![keenern](https://avatars.discourse-cdn.com/v4/letter/k/779978/32.png) [@keenern](https://forum.inductiveautomation.com/u/keenern)\
**Post date:** [May 31, 2024, 7:53pm UTC](https://forum.inductiveautomation.com/t/system-util-invokeasynchronous-threading-details/91221/3 "2024-05-31T19:53:15Z")

</div>

Thank you. This answered my question. This is what I figured but wanted a verification as well. 🙂

---

<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:** [May 31, 2024, 8:09pm UTC](https://forum.inductiveautomation.com/t/system-util-invokeasynchronous-threading-details/91221/4 "2024-05-31T20:09:13Z")

</div>

Also, the threads created by invokeAsynchronous are heavyweight OS threads. There's a non-trivial cost to their creation. If you're willing to trade off engineering effort, reaching into Java's primitives to create your own executor service with it's own managed threadpool can give you equivalent or better performance with reduced memory usage.

---

<div class="post-metadata">

**Author:** ![Alex\_Ceithamer](https://avatars.discourse-cdn.com/v4/letter/a/a3d4f5/32.png) [@Alex\_Ceithamer](https://forum.inductiveautomation.com/u/Alex_Ceithamer)\
**Post date:** [February 3, 2025, 4:02pm UTC](https://forum.inductiveautomation.com/t/system-util-invokeasynchronous-threading-details/91221/5 "2025-02-03T16:02:59Z")

</div>

I think this is a given but I want to confirm  
.  
Each system.util.invokeAsynchronous() call creates a new heavyweight OS thread, and **does not re-use threads** (i.e., there is no internal thread pool being used to minimize creation costs of threads)?

In which case using:

`from java.util.concurrent import Executors`  
`executor = Executors.newFixedThreadPool(20)`

and storing the executor in the global dictionary  
(with careful management to avoid memory leaks)  
would be advantageous in cases where a loop is running many new threads.

Is that correct?

---

<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:** [February 3, 2025, 4:24pm UTC](https://forum.inductiveautomation.com/t/system-util-invokeasynchronous-threading-details/91221/6 "2025-02-03T16:24:49Z")

</div>

Yes, as long as the 20-thread limit introduce deadlock possibilities. The most effective number of threads might be higher if each thread has significant `.sleep()` time, or time waiting on I/O.

---

<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:** [February 3, 2025, 4:39pm UTC](https://forum.inductiveautomation.com/t/system-util-invokeasynchronous-threading-details/91221/7 "2025-02-03T16:39:40Z")

</div>

You could also, with [some amount of effort](https://forum.inductiveautomation.com/t/issues-when-using-system-util-invokeasynchronous-i-get-a-nonetype-object-is-not-callable-error/97022/11), use the standard libraries' built in ForkJoinPool used for the `CompletableFuture` API. If we were designing `invokeAsynchronous` again from scratch, this is what we'd almost certainly use 'under the hood', but the function predates `CompletableFuture` entirely.
