# Question on stopping asynchronous threads in Ignition

**URL:** <https://forum.inductiveautomation.com/t/question-on-stopping-asynchronous-threads-in-ignition/70861>\
**Category:** Ignition\
**Tags:** python, perspective, vision, ignition81\
**Created:** [March 9, 2023, 7:50pm UTC](https://forum.inductiveautomation.com/t/question-on-stopping-asynchronous-threads-in-ignition/70861 "2023-03-09T19:50:41Z")\
**Posts on this page:** 3\
**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:** [March 9, 2023, 7:50pm UTC](https://forum.inductiveautomation.com/t/question-on-stopping-asynchronous-threads-in-ignition/70861/1 "2023-03-09T19:50:41Z")

</div>

I'd like to share my findings on the issue of running and managing asynchronous threads in Ignition, for anyone going down the same rabbit hole, but also curious if this is a big no-no in Ignition. So far we haven't had any issues with this but I am curious if anyone else has done something similar and achieved success with it.

We were trying to create asynchronous threads that can start/stop listening to a serial port opened up on a client. We wanted to keep this in vision and have this "driver" communicate to perspective as well by writing to a UDT that perspective reads. We could have went with SFC's alternatively, or an external .NET service running on the client that talks to OPC, but these seem to be "unclean" solutions.

So to do this, we went with making asynchronous threads to open/close serial communication to the machine plugged into the local asset.

In order to close/end the serial communication, we have to shut off the asynchronous call which we can do with a timeout on no data change to end the thread, but also, we found that we can use the following to locate rogue or orphaned threads:

```python
def get_thread(name):
	# Get the Java Thread object in java.lang.Thread
	from java.lang import Thread
	# Get all of the currently running threads from the current java stack trace
	threads = Thread.getAllStackTraces()
	
	# Assume only one thread exists that matches name, modifiable to return multiple threads if more than 1 match
	result = None
	for thread in threads:
		thread_name = thread.name
		# Thread name matches known input thread name
		if str(thread_name) == str(name):
			result = thread
			break
	return result

```

Followed by application of

```python
def stop_thread(name):
	thread = get_thread(name)
	thread.stop()

```

Using `thread.stop()` is sort of frowned upon, but does it cause issues like not being garbage collected, etc.? I don't know that I have seen this solution in the forums. We have been able to shut off calls from thread generators like

```python
def make_thread(name, target=None, callback=None, timeout=60):
	import threading
	thread = threading.Thread(target=target, name=name, kwargs={"timeout":timeout, "callback":callback})
	thread.start()
	return thread

```

or

```python
def make_ign_thread(name, target=None, callback=None, timeout=60):
	thread = system.util.invokeAsynchronous(function=target, description=name, kwargs={"timeout":timeout, "callback":callback}))
	# Probably need to store this thread name in a DB or tag, it looks like [Thread-23]
	thread_name = thread.getName()
	return thread

```

that are no longer persistent in the current context (i.e. the script stopped but the threads continue to exist).

Anyone have experience doing this and can chime in on the pros/cons of this? Will the world be forever altered by my blasphemy? Will I regret this in the next 137 years of my existence?

Cheers,  
Roger

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [March 9, 2023, 9:18pm UTC](https://forum.inductiveautomation.com/t/question-on-stopping-asynchronous-threads-in-ignition/70861/2 "2023-03-09T21:18:48Z")

</div>

This may not answer all your questions, but it is good advice.

> [@Managing multiple asynchronous threads](https://forum.inductiveautomation.com/t/managing-multiple-asynchronous-threads/37185/2):
>
> To manage long-running jython threads through scripting restarts, you need to: Place the thread object in a dictionary that retains its content through script restarts. I used to recommend the dictionary from system.util.getGlobals(), but that is no longer suitable. I created a free [Life Cycle Module](http://forum.inductiveautomation.com/t/system-util-getglobals-not-persisted-across-designer-save/33869/14) that provides such dictionaries going forward. Write the asynchronous function’s loop so that it regularly checks [Thread.interrupted()](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupted--), particularly after any java I/O operations. Clean up …

---

<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 9, 2023, 10:16pm UTC](https://forum.inductiveautomation.com/t/question-on-stopping-asynchronous-threads-in-ignition/70861/3 "2023-03-09T22:16:01Z")

</div>

The reasons not to manually call `stop` are highlighted in the javadoc:  
[https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Thread.html#stop()](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Thread.html#stop())

`interrupt()` is safer, to indicate to a thread that it should stop a busy-wait: [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Thread.html#interrupt()](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Thread.html#interrupt())

If you find yourself making arbitrary threads for your own purposes often, I would _highly_ recommend using one of the executor factories to create a thread pool _once_, to which you can dictate your own work:  
[https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/Executors.html#newFixedThreadPool(int)](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/Executors.html#newFixedThreadPool(int))

Any threads you submit to that execution pool should either monitor their own sentinel signal or just check `Thread.currentThread.isInterrupted()` so you can propagate cancellation cleanly.
