【发布时间】:2014-12-02 18:00:49
【问题描述】:
我有一个小型聊天客户端,它将所有历史记录存储在 sqlite 数据库中。当用户在我的应用程序中单击history 选项卡时,我的应用程序会获取所有相关历史记录并将其显示在QWebView 中。我从下面的后台线程dbThread 获取,然后发送信号以相应地更新QWebView。
这工作正常,直到数据库增长。当数据库变大时,应用程序开始几乎崩溃。 GUI 会在几秒钟内无响应,直到所有内容都加载完毕(4-6 秒),具体取决于database 的大小。
我已经尝试在信号上添加Qt::QueuedConnection,并且如上所述,我正在处理来自background thread 的所有database 查询。
我猜我发出信号的速度太快了。任何想法如何解决这个问题?
信号
connect(dbtrad, SIGNAL(addAllHistoryMessage(QString, QString, QString, QString, QString)), this, SLOT(addAllHistoryMessage(QString, QString, QString, QString, QString)), Qt::QueuedConnection);
connect(dbtrad, SIGNAL(addAllHistoryMessageInner(QString, QString, QString, QString, QString)), this, SLOT(addAllHistoryMessageInner(QString, QString, QString, QString, QString)), Qt::QueuedConnection);
从 sqlite 数据库中获取历史记录的代码:
// Loads all local history
void dbThread::loadAllHistory(QString agentID, QString agentName) {
bool ret = false;
bool retInner = false;
QString retVal = "";
QDateTime dateTime = dateTime.currentDateTime();
QString dateTimeForTodayCheck = dateTime.toString("yyyy-MM-dd");
if (db.isOpen()) {
QSqlQuery query(db);
QSqlQuery queryInner(db);
ret = query.exec(QString("SELECT channelID, sender, time, message from chatHistory WHERE sender != 'ServerMessage' AND channelID NOT LIKE '%Agent%' GROUP BY channelID order by time DESC;"));
if (ret) {
while (query.next()) {
QString channelID = query.value(0).toString();
QString sender = query.value(1).toString();
QString time = query.value(2).toString();
QString msg = query.value(3).toString();
QString timeStr;
QString fmt = "yyyy-MM-dd hh:mm:ss";
QDateTime dt = QDateTime::fromString(time, fmt);
QDateTime dtCompare = QDateTime::fromString(time, fmt);
if(dateTimeForTodayCheck == dtCompare.toString("yyyy-MM-dd")) { // If today
timeStr = "Today " + dt.toString("hh:mm");
} else {
timeStr = dt.toString("dd MMM yyyy");
}
if(sender == agentID) {
sender = agentName;
}
// Grab all the tags
QString tempTagsForChannelID = getHistoryTagsString(channelID);
emit addAllHistoryMessage(channelID, sender, timeStr, msg, tempTagsForChannelID);
// Load sub-history
retInner = queryInner.exec(QString("SELECT * from chatHistory WHERE sender != 'ServerMessage' AND channelID = '%1' and message != '%2' order by time DESC;").arg(channelID).arg(msg));
if (retInner) {
while (queryInner.next()) {
QString channelIDInner = queryInner.value(0).toString();
QString senderInner = queryInner.value(1).toString();
QString timeInner = queryInner.value(4).toString();
QString msgInner = queryInner.value(2).toString();
QString timeStr2;
QString fmt = "yyyy-MM-dd hh:mm:ss";
QDateTime dt = QDateTime::fromString(timeInner, fmt);
QDateTime dtCompare = QDateTime::fromString(timeInner, fmt);
if(dateTimeForTodayCheck == dtCompare.toString("yyyy-MM-dd")) { // If today
timeStr2 = "Today " + dt.toString("hh:mm");
} else {
timeStr2 = dt.toString("dd MMM yyyy");
}
if(senderInner == agentID) {
senderInner = agentName;
}
emit addAllHistoryMessageInner(channelIDInner, senderInner, timeStr2, msgInner, tempTagsForChannelID);
}
}
}
}
}
}
我要更新的代码:
void MainWindow::addAllHistoryMessageInner(QString channelIDInner, QString senderInner, QString timeStr2, QString msgInner, QString tempTagsForChannelID) {
ui->webViewHistory->page()->mainFrame()->evaluateJavaScript("$('#history tbody').append('<tr id=\"" + channelIDInner+ "\" class=\"hiddenRow\"><td>" + senderInner + "</td><td align=\"center\">" + timeStr2 + "</td><td align=\"center\" style=\"word-wrap:break-word;\">" + msgInner.remove(QRegExp("<[^>]*>")) + "</td><td align=\"center\">" + tempTagsForChannelID + "</td></tr>');undefined");
}
void MainWindow::addAllHistoryMessage(QString channelID, QString sender, QString timeStr, QString msg, QString tempTagsForChannelID) {
ui->webViewHistory->page()->mainFrame()->evaluateJavaScript("$('#history tbody').append('<tr id=\"" + channelID + "\"><td>" + sender + "</td><td align=\"center\">" + timeStr + "</td><td align=\"center\" style=\"word-wrap:break-word;\">" + msg.remove(QRegExp("<[^>]*>")) + "</td><td align=\"center\" style=\"word-wrap:break-word;\">" + tempTagsForChannelID + "</td></tr>');undefined");
}
编辑:dbThread 的实现
thread = new QThread(this);
dbtrad = new dbThread();
dbtrad->moveToThread(thread);
编辑 2:我就是这样称呼loadAllHistory
我创建一个信号:
connect(this, SIGNAL(loadAllHistoryS(QString, QString)), dbtrad, SLOT(loadAllHistory(QString, QString)));
然后这样称呼它:
emit loadAllHistoryS(agentID, agentName);
【问题讨论】:
-
您的数据库连接是否在
dbThread中创建?dbThread真的是在一个单独的线程中运行的,它是如何实现的? -
我正在打开
dbThread内的数据库连接,请参阅上面线程的实现:) -
你怎么称呼
loadAllHistory? -
更新我的称呼
-
您是否在
thread.start()的线程上启动了事件循环?会不会结果是在同一个线程而不是后台线程上有效地同步执行(导致主线程由于数据库I/O而阻塞)?
标签: c++ multithreading qt