2013-08-20 35 views
1

我已經編寫了一個PySide Windows應用程序,它使用libvlc來顯示視頻,記錄擊鍵並將關於這些擊鍵的聚集信息寫入文件。我遇到兩個導致應用程序崩潰的錯誤(其他問題在這裏 - >https://stackoverflow.com/questions/18326943/pyside-qlistwidget-crash)。PySide計時器/線程崩潰

應用程序每五分鐘在視頻上寫入擊鍵文件。用戶可以更改播放速度,因此五分鐘的時間間隔可能需要多於或少於五分鐘;它不受計時器控制。

視頻在文件寫入時繼續播放,所以我創建了一個從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 

doIntervalChange從內QWidget的使用信號調用。 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崩潰。有什麼建議麼?請注意,崩潰似乎是隨機的;有時我可以使用應用程序(只需連續按下相同的按鍵)一個小時,而不會崩潰,有時它會在前幾個間隔內。由於重現崩潰的難度,我認爲這些代碼行是問題,但我不是100%確定的。

回答

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?

+0

我發佈的代碼被簡化了,在發佈問題之前,我實際上已經嘗試過了。謝謝你的嘗試 – virtuesplea

+0

啊。值得一試!你有可能發佈一個顯示問題的簡單例子嗎? –

+0

這個項目很早以前就已經到期了,我最終用我更熟悉的語言重寫了整個應用程序。這是相當複雜的,將其簡化爲一個簡單的例子會很費時間,而且現在我不會激勵它。感謝您盡力幫忙,這對我來說是非常令人沮喪的。 – virtuesplea