Sublime Forum

How to correctly run threads?

#1

Hello,

I am writing here bacause I am trying to know how threads work with Sublime Text. I am trying to write plugin which connects to the external service and I need to have some kind of listener working in the thread as long as user wants to be connected.

Just imagine the situation. We have an Python module with only one class. In this class we can find some methods. The most important ones are: connect, send_data and disconnect. We are creating only one instance of given class. Nextly we run connect method (if handshake ends successfully, listener starts in the background). In the meantime we can use send_data method as much as we want and after every send_data method call there will be something to read by listener. User can disconnect from the service at any time. This is the scenerio I want to reach.

For now I have problem with more, more easily topic:

import sublime
import sublime_plugin
import threading

class Background(threading.Thread):
	__instance = None

	@staticmethod
	def get_instance():
		if Background.__instance == None:
			Background()

		return Background.__instance

	def __init__(self):
		if Background.__instance != None:
			raise Exception("Cannot create next instance of this class (singleton).")
		else:
			Background.__instance = self
			self.counter = 1
			threading.Thread.__init__(self)

	def run(self):
		while self.counter <= 10000:
			print(str(self.counter))
			self.counter = self.counter + 1

class TestCommand(sublime_plugin.WindowCommand):
	def run(self):
		bg = Background.get_instance()
		bg.start()

This piece of code makes Sublime Text 3 UI freeze. How should be it written correctly to avoid freezing?

Cheers

0 Likes

#2

Do import time, and change your run method to


	def run(self):
		while self.counter <= 10000:
			print(str(self.counter))
			self.counter = self.counter + 1
            time.sleep(0.1)

and you’ll see that your thread is actually working. I’m not entirely sure why ST freezes, but I’m speculating that the global interpreter lock is held until after your run method is done without the time.sleep. Of course, in a real implementation you would not use time.sleep but rather wait in some way on the background process.

0 Likes

#3

Thank you very much. Connection issue fixed. Now there is no freeze. I have one more problem, I cannot disconnect.

With this simple example, it works:

import sublime
import sublime_plugin
import threading
import time

class Background(threading.Thread):
	__instance = None

	@staticmethod
	def get_instance():
		if Background.__instance == None:
			Background()

		return Background.__instance

	def __init__(self):
		if Background.__instance != None:
			raise Exception("Cannot create next instance of this class (singleton).")
		else:
			Background.__instance = self
			self.running = True
			self.counter = 1
			threading.Thread.__init__(self)

	def run(self):
		while self.running:
			print(str(self.counter))
			self.counter = self.counter + 1
			time.sleep(0.1)

	def stop(self):
		self.running = False

class TestCommand(sublime_plugin.WindowCommand):
	def run(self):
		bg = Background.get_instance()
		bg.start()

class StopCommand(sublime_plugin.WindowCommand):
	def run(self):
		bg = Background.get_instance()
		bg.stop()

But I am using my wrapper that use asyncio module. In disconnect method I am using:

        logger.info("Disconnecting...")
		self.pipe_writer.close()
		self.event_loop.run_until_complete(self.proper_close())
		self.event_loop.close()
		self.is_connected = False
		self.pipe_writer = None
		self.pipe_reader = None
		self.event_loop = None
		logger.info("Disconncted")

In the console I see this two logger messages, I can execute disconnect method one more time, but with exceptions because pipe_writer is None. What is intresting, I am still connected and executing connect method one more time confirms it with logger message “Already connected”. With linux command htop I can see that after disconnect method one of the Sublime Text processes disappears.

Weird thing… Maybe someone has an idea?

Cheers

0 Likes

#4

The asyncio module was introduced in python 3.4. ST uses python 3.3.

0 Likes

#5

I know, I installed it manually and changed syntax to the old one. Working very well.

0 Likes

#6

Check this…Python Threading Basics

0 Likes