Upon pressing a listbox row, a thread is started which:
The row can be pressed multiple times, meaning it can spawn multiple threads, which may end up running simultaneously.
The issue is that if the row is pressed very quickly multiple times, the treeview ends up with duplicate entries. This is caused by the multiple threads running in parallel, all trying to add the same set of items the treeview.
The solution to this issue would be to only ever allow one instance of the thread running at any time. This could be done by either:
Preventing new thread instances from starting if the thread is currently running
Stop the already running instance of the thread, and only then starting a new one
The problem is that I do not know how to implement either of those solutions.
Code:
class Main(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.connect("destroy", Gtk.main_quit)
self.liststore = Gtk.ListStore(str)
self.treeview = Gtk.TreeView()
self.treeview.set_model(self.liststore)
cellrenderertext = Gtk.CellRendererText()
treeviewcolumn = Gtk.TreeViewColumn("Items", cellrenderertext, text=0)
self.treeview.append_column(treeviewcolumn)
self.button = Gtk.Button(label='Button')
box = Gtk.Box()
box.set_orientation(Gtk.Orientation.VERTICAL)
box.add(self.button)
box.add(self.treeview)
self.add(box)
self.button.connect('clicked', self.button_clicked)
def button_clicked(self, widget):
def threaded():
self.liststore.clear()
self.liststore.append(['first_item'])
time.sleep(0.1)
self.liststore.append(['second_item'])
time.sleep(0.1)
self.liststore.append(['third_item'])
threading.Thread(target=threaded, daemon=True).start()
if __name__ == '__main__':
window = Main()
window.show_all()
Gtk.main()
I added the time.sleep(0.1)
to simulate the delay between each item being added.
Pressing the button multiple times will result in duplicate entries appearing in the treeview. The expected output is:
first_item
second_item
third_item
However, pressing the button really quickly instead results in:
first_item
third_item
second_item
third_item
You should use variable to keep thread and check this variable.
In __init__
set variable
self.thread = None
and when you press button then check this variable
#if (self.thread in None) or (self.thread.is_alive() is False):
if not self.thread or not self.thread.is_alive():
self.thread = threading.Thread(...)
self.thread.start()
Instead of checking is_alive()
you could set self.thread = None
at the end of thread.