PySide计时器/线程崩溃

时间:2013-08-20 03:53:47

标签: multithreading pyqt pyside

我编写了一个PySide Windows应用程序,它使用libvlc来显示视频,记录击键,并将有关这些击键的汇总信息写入文件。我遇到了导致应用程序崩溃的两个错误(此处的其他问题 - > https://stackoverflow.com/questions/18326943/pyside-qlistwidget-crash)。

应用程序在视频上每隔五分钟写一次击键文件。用户可以改变播放速度,这样五分钟的间隔可能需要多于或少于五分钟;它不受计时器的控制。

视频在写入文件时继续播放,因此我创建了一个继承自threading.Thread的对象来创建文件 - IntervalFile。有关要写入的文件的一些信息在构造函数中传递; IntervalFile根本不访问其父(主QWidget)。这是我在应用程序中使用的唯一线程对象。在任何地方都没有宣布计时器。

间歇性地,应用程序将崩溃并且我将收到以下消息:“ QObject :: killTimers:无法从另一个线程停止计时器”。

创建IntervalFile的代码是(CustomWidget的一部分,继承自QWidget):

def doIntervalChange(self):
  ...
  ifile = IntervalFile(5, filepath, dbpath) # db is sqlite, with new connection created within IntervalFile
  ifile.start()
  #end of def

使用信号从QWidget中调用doIntervalChange。 IntervalFile是:

class IntervalFile(threading.Thread):
  def __init__(self, interval, filepath, dbpath):
    # declaration of variables

    threading.Thread.__init__(self)

  def run(self):
    shutil.copy('db.local', self.dbPath) # because db is still being used in main QWidget
    self.localDB = local(self.dbPath) # creates connection to sqlite db, with sql within the object to make db calls easier

    # query db for keystroke data
    # write file

    self.localDB.close()
    self.localDB = None

    os.remove(self.dbPath) # don't need this copy anymore

当ifile.start()被注释掉时,我看不到killTimers崩溃。有什么建议?请注意,崩溃似乎是随机的;有时我可以使用应用程序(只是一遍又一遍地按相同的按键)一小时而不会崩溃,有时候它会在前几个时间间隔内。由于重现崩溃的困难,我认为这些代码行是问题,但我不是百分百肯定。

1 个答案:

答案 0 :(得分:0)

我很确定你需要持有对线程对象的引用。当你的doIntervalChange()方法完成时,没有任何东西持有对线程对象(ifile)的引用,因此它可以被垃圾收集。据推测这就是崩溃随机发生的原因(如果线程在对象被垃圾收集之前完成它的任务,那么你就没有问题了。)

不完全确定创建QTimers的是什么,但我相当肯定这不会影响我提出的解决方案!

因此,在doIntervalChange()中,在列表中保存对ifile的引用,并在线程完成执行时定期清理列表。看一下这个想法(如果有更好的清理线程的方法出现在那篇文章中,那就实现它!):Is there a more elegant way to clean up thread references in python? Do I even have to worry about them?