大家好,我想請求大家幫忙一個問題。我用QT平臺,開發了一個有關資料庫的程式。用的方式就是網上看到的基本的資料庫操作。我先寫了一個實驗程式,是沒有問題的,保存了一百萬條資料,都是正常運行的。然后把我測驗過的代碼,放入我的新程式中,就出現了一個問題。
我在Widget類中,加了一個回呼函式。如果收到硬體發給我的中斷,先觸發回呼函式,回呼函式是靜態非成員函式。回呼函式被觸發之后,會發送事件給Widget類中的一個成員函式。Widget類中的這個成員函式,具體作用就是把得到的資料進行保存。保存資料的代碼就是我前面實驗過的資料庫的代碼。整個程式是可以正常運行的,但是會出現一個巨大的問題,就是程式一直在申請很多句柄。隨著保存的資料量越大,句柄量越來越多,到最后,整個系統的句柄都被用完了,系統沒辦法進行任何操作。我在任務管理器中看了,記憶體沒有消耗,CPU也沒有,就是句柄在瘋狂的增加。程式跑在Win7的系統上,作業系統直接提示,系統資源耗盡,什么都點不了,最后只能重啟電腦。
資料庫操作部分的大概邏輯如下:
QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");
database.setDatabaseName("VMIC_DataBase.db");
database.transaction();
for (int i = 0; i < NUM; i++)
{
QString qsStr;
qsStr.sprintf("insert into member values(%d, '%s')", nDatabaseID, cRecBufAssem[i]);
bool success = query.exec(qsStr);
}
if(!QSqlDatabase::database().commit())
{
qDebug() << QSqlDatabase::database().lastError(); //提交
if(!QSqlDatabase::database().rollback())
{
qDebug() << QSqlDatabase::database().lastError(); //回滾
}
}經過我的排查,其中消耗句柄的應該就是這句:
bool success = query.exec(qsStr);
我想問一下大家,為什么會出現這種情況,我之前的實驗程式,也有這個陳述句,怎么就沒有消耗句柄呢。這個問題要怎么解決,如何不申請或者說能夠釋放掉句柄呢。
我是新手,對QT不熟練,請大家解答的時候,稍微詳細一些,謝謝大家,多謝。在線等。
uj5u.com熱心網友回復:
一般都是main函式執行資料庫打開,最后程式關閉時候關閉資料庫,而不是每次使用資料庫都打開關閉一次!那樣每次都需要用句柄!uj5u.com熱心網友回復:
我沒有,我當然沒有每一次都打開,保存資料,再關閉,那樣沒必要啊,我整個操作只執行一次,這個我知道。
uj5u.com熱心網友回復:
沒有背景關系,不好判斷。我大致改成這樣,你再試試QSqlDatabase database = QSqlDatabase::database("QSQLITE");
if ( database.isValid() == false ) {
database = QSqlDatabase::addDatabase("QSQLITE");
database.setDatabaseName("VMIC_DataBase.db");
}
QSqlQuery query;
query.prepare("insert into member values(?, ?)");
database.transaction();
for (int i = 0; i < NUM; i++)
{
query.bindValue(0, nDatabaseID, QSql::In);
query.bindValue(1, cRecBufAssem[i], QSql::In);
bool success = query.exec();
}
if(!QSqlDatabase::database().commit())
{
qDebug() << QSqlDatabase::database().lastError(); //提交
if(!QSqlDatabase::database().rollback())
{
qDebug() << QSqlDatabase::database().lastError(); //回滾
}
}
uj5u.com熱心網友回復:
if(!QSqlDatabase::database().commit())
{
qDebug() << QSqlDatabase::database().lastError(); //提交
if(!QSqlDatabase::database().rollback())
{
qDebug() << QSqlDatabase::database().lastError(); //回滾
}
}
這段忘記改了,改成:
if(!database.commit())
{
qDebug() << database.lastError(); //提交
if(!database.rollback())
{
qDebug() << database.lastError(); //回滾
}
}
uj5u.com熱心網友回復:
朋友,謝謝你的熱情幫助,我試了,還是不行。我想,是不是和回呼有關系啊,是不是回呼函式實質上和Widget不是一個執行緒,開啟了多執行緒導致了什么意外的后果。
uj5u.com熱心網友回復:
回呼函式當然很大可能和widget不是同一個執行緒。。。
你列印下執行緒ID就知道了。
qDebug()<<num<<"thread start:"<<QThread::currentThreadId();
多執行緒操作資料庫是不安全的!!!
所以建議資料庫操作還是另外建一個作業執行緒來管理,
ui需要資料庫操作,就給它發信號就可以了,讓信號在佇列里排隊
uj5u.com熱心網友回復:
資料庫執行緒安全我也不確認QT做了沒,這個你最好排查下。轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/117105.html
標籤:Qt
上一篇:AS求解答
