Threaded task hangs and does not run in background

I’m using ObjectListView to display data sourced from a local sqlite database. Sqlalchemy is used to perform sql queries.

I want to remove the items selected from the ListCtrl/ObjectListView, then in a thread run a query to delete the records associated with those items from the database so the GUI does not hang. Here is what my code looks like (with all the extraneous parts cut out):

class FileWindow(wx.Frame):

def __init__(self):

    wx.Frame.__init__(self)

    panel = wx.Panel(self, -1)

    self.fileOlv = FastObjectListView(panel, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)

    self.fileOlv.Bind(wx.EVT_KEY_DOWN, self.deleteFile)

def deleteFile(self,evt):

    t=threading.Thread(target=self.__deleteFile)

    t.start()

def __deleteFile(self):

    removedFiles = self.fileOlv.GetSelectedObjects()

    self.fileOlv.RemoveObjects(removedFiles)

    # Gui freezes until self.deleteFileInThread is finished running

    wx.CallAfter(self.deleteFileInThread, removedFiles)

def deleteFileInThread(self, removedFiles):

    d = file_collection.delete().where(file_collection.c.id == bindparam('file_id'))

    for file in removedFiles:

        self.conn.execute(d, file_id = file.id)

However GUI hangs until the for loop is finished. What is incorrect about my thread and wx.CallAfter implementation?

I ran into a similar issue with one of my apps a while back. What I ended up doing was creating a Threading class. Here is a small snippet to point you in the same direction. Please keep in mind you will most likely need to change the code a little to properly connect to your database.

from threading import Thread

Do not forget the rest of your imports.

class ThreadedDelete(Thread):

def init(self, removedFiles):

Thread.init(self)

self.start()

self.removedFiles = removedFiles

def run(self):

d = file_collection.delete().where(file_collection.c.id == bindparam(‘file_id’))

for file in self.removedFiles:

self.conn.execute(d, file_id = file.id)

class FileWindow(wx.Frame):

def init(self):

wx.Frame.init(self)

panel = wx.Panel(self, -1)

self.fileOlv = FastObjectListView(panel, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)

self.fileOlv.Bind(wx.EVT_KEY_DOWN, self.deleteFile)

def __deleteFile(self):

removedFiles = self.fileOlv.GetSelectedObjects()

self.fileOlv.RemoveObjects(removedFiles)

Gui freezes until self.deleteFileInThread is finished running

wx.CallAfter(ThreadedDelete, removedFiles)

-Mike S

···

On Monday, February 24, 2014 4:19:40 AM UTC-5, RedHotChiliPepper wrote:

I’m using ObjectListView to display data sourced from a local sqlite database. Sqlalchemy is used to perform sql queries.

I want to remove the items selected from the ListCtrl/ObjectListView, then in a thread run a query to delete the records associated with those items from the database so the GUI does not hang. Here is what my code looks like (with all the extraneous parts cut out):

class FileWindow(wx.Frame):

def __init__(self):
    wx.Frame.__init__(self)
    panel = wx.Panel(self, -1)
    self.fileOlv = FastObjectListView(panel, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
    self.fileOlv.Bind(wx.EVT_KEY_DOWN, self.deleteFile)
def deleteFile(self,evt):
    t=threading.Thread(target=self.__deleteFile)
    t.start()
def __deleteFile(self):
    removedFiles = self.fileOlv.GetSelectedObjects()
    self.fileOlv.RemoveObjects(removedFiles)
    # Gui freezes until self.deleteFileInThread is finished running
    wx.CallAfter(self.deleteFileInThread, removedFiles)
def deleteFileInThread(self, removedFiles):
    d = file_collection.delete().where([file_collection.c.id](http://file_collection.c.id) == bindparam('file_id'))
    for file in removedFiles:
        self.conn.execute(d, file_id = [file.id](http://file.id))

However GUI hangs until the for loop is finished. What is incorrect about my thread and wx.CallAfter implementation?

This did the trick, the bit with passing the class and the first argument to the constructor to wx.CallAfter was the piece of logic I was missing.

···

On Monday, February 24, 2014 11:17:24 AM UTC-5, Mike Stover wrote:

I ran into a similar issue with one of my apps a while back. What I ended up doing was creating a Threading class. Here is a small snippet to point you in the same direction. Please keep in mind you will most likely need to change the code a little to properly connect to your database.

from threading import Thread

Do not forget the rest of your imports.

class ThreadedDelete(Thread):

def init(self, removedFiles):

Thread.init(self)

self.start()

self.removedFiles = removedFiles

def run(self):

d = file_collection.delete().where(file_collection.c.id == bindparam(‘file_id’))

for file in self.removedFiles:

self.conn.execute(d, file_id = file.id)

class FileWindow(wx.Frame):

def init(self):

wx.Frame.init(self)

panel = wx.Panel(self, -1)

self.fileOlv = FastObjectListView(panel, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)

self.fileOlv.Bind(wx.EVT_KEY_DOWN, self.deleteFile)

def __deleteFile(self):

removedFiles = self.fileOlv.GetSelectedObjects()

self.fileOlv.RemoveObjects(removedFiles)

Gui freezes until self.deleteFileInThread is finished running

wx.CallAfter(ThreadedDelete, removedFiles)

-Mike S

On Monday, February 24, 2014 4:19:40 AM UTC-5, RedHotChiliPepper wrote:

I’m using ObjectListView to display data sourced from a local sqlite database. Sqlalchemy is used to perform sql queries.

I want to remove the items selected from the ListCtrl/ObjectListView, then in a thread run a query to delete the records associated with those items from the database so the GUI does not hang. Here is what my code looks like (with all the extraneous parts cut out):

class FileWindow(wx.Frame):

def __init__(self):
    wx.Frame.__init__(self)
    panel = wx.Panel(self, -1)
    self.fileOlv = FastObjectListView(panel, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
    self.fileOlv.Bind(wx.EVT_KEY_DOWN, self.deleteFile)
def deleteFile(self,evt):
    t=threading.Thread(target=self.__deleteFile)
    t.start()
def __deleteFile(self):
    removedFiles = self.fileOlv.GetSelectedObjects()
    self.fileOlv.RemoveObjects(removedFiles)
    # Gui freezes until self.deleteFileInThread is finished running
    wx.CallAfter(self.deleteFileInThread, removedFiles)
def deleteFileInThread(self, removedFiles):
    d = file_collection.delete().where([file_collection.c.id](http://file_collection.c.id) == bindparam('file_id'))
    for file in removedFiles:
        self.conn.execute(d, file_id = [file.id](http://file.id))

However GUI hangs until the for loop is finished. What is incorrect about my thread and wx.CallAfter implementation?

Glad to have helped. Hopefully others will see this if they experience similar issues.

···

On Wednesday, February 26, 2014 7:37:24 PM UTC-5, RedHotChiliPepper wrote:

This did the trick, the bit with passing the class and the first argument to the constructor to wx.CallAfter was the piece of logic I was missing.

On Monday, February 24, 2014 11:17:24 AM UTC-5, Mike Stover wrote:

I ran into a similar issue with one of my apps a while back. What I ended up doing was creating a Threading class. Here is a small snippet to point you in the same direction. Please keep in mind you will most likely need to change the code a little to properly connect to your database.

from threading import Thread

Do not forget the rest of your imports.

class ThreadedDelete(Thread):

def init(self, removedFiles):

Thread.init(self)

self.start()

self.removedFiles = removedFiles

def run(self):

d = file_collection.delete().where(file_collection.c.id == bindparam(‘file_id’))

for file in self.removedFiles:

self.conn.execute(d, file_id = file.id)

class FileWindow(wx.Frame):

def init(self):

wx.Frame.init(self)

panel = wx.Panel(self, -1)

self.fileOlv = FastObjectListView(panel, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)

self.fileOlv.Bind(wx.EVT_KEY_DOWN, self.deleteFile)

def __deleteFile(self):

removedFiles = self.fileOlv.GetSelectedObjects()

self.fileOlv.RemoveObjects(removedFiles)

Gui freezes until self.deleteFileInThread is finished running

wx.CallAfter(ThreadedDelete, removedFiles)

-Mike S

On Monday, February 24, 2014 4:19:40 AM UTC-5, RedHotChiliPepper wrote:

I’m using ObjectListView to display data sourced from a local sqlite database. Sqlalchemy is used to perform sql queries.

I want to remove the items selected from the ListCtrl/ObjectListView, then in a thread run a query to delete the records associated with those items from the database so the GUI does not hang. Here is what my code looks like (with all the extraneous parts cut out):

class FileWindow(wx.Frame):

def __init__(self):
    wx.Frame.__init__(self)
    panel = wx.Panel(self, -1)
    self.fileOlv = FastObjectListView(panel, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
    self.fileOlv.Bind(wx.EVT_KEY_DOWN, self.deleteFile)
def deleteFile(self,evt):
    t=threading.Thread(target=self.__deleteFile)
    t.start()
def __deleteFile(self):
    removedFiles = self.fileOlv.GetSelectedObjects()
    self.fileOlv.RemoveObjects(removedFiles)
    # Gui freezes until self.deleteFileInThread is finished running
    wx.CallAfter(self.deleteFileInThread, removedFiles)
def deleteFileInThread(self, removedFiles):
    d = file_collection.delete().where([file_collection.c.id](http://file_collection.c.id) == bindparam('file_id'))
    for file in removedFiles:
        self.conn.execute(d, file_id = [file.id](http://file.id))

However GUI hangs until the for loop is finished. What is incorrect about my thread and wx.CallAfter implementation?