c++ - Qt GUI becomes unresponsive emitting signals too fast -


i've got small chat client stores history in sqlite database. when user clicks on history tab in application app fetches relevant history , displays in qwebview. im fetching background thread dbthread below , sending signals update qwebview accordingly.

this works fine, until database grows. when database gets larger app starts crashes. gui unresponsive few seconds until loaded (4-6 secs) depending on database size.

i've tried add qt::queuedconnection on signals , mentioned above i'm handling database queries background thread.

i'm guessing i'm emitting signals fast. ideas how solve this?

signals

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); 

code fetches history sqlite database:

// loads 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 chathistory sender != 'servermessage' , channelid not '%agent%' group channelid order 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 tags                 qstring temptagsforchannelid = gethistorytagsstring(channelid);                  emit addallhistorymessage(channelid, sender, timestr, msg, temptagsforchannelid);                  // load sub-history                 retinner = queryinner.exec(qstring("select * chathistory sender != 'servermessage' , channelid = '%1' , message != '%2' order 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);                     }                 }             }         }     } } 

my code update:

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"); } 

edit: implementation of dbthread

thread = new qthread(this); dbtrad = new dbthread(); dbtrad->movetothread(thread); 

edit 2: how call loadallhistory

i create signal:

connect(this, signal(loadallhistorys(qstring, qstring)), dbtrad, slot(loadallhistory(qstring, qstring))); 

and call this:

emit loadallhistorys(agentid, agentname); 

the problem is, main thread interrupted every single row in innerquery. destroys benefits of loading data in separate thread. overhead of signal/slot communication on thread boundaries higher costs of loading single row database.

i recommend collect rows in qlist instance while loop. when done, push complete result via 1 signal invocation main thread:

first declare simple class storing history items:

class historyitem {     public:         qstring channelid;         /* additonal fields omitted brevity */         /* also, private fields getters , setters better */ } 

then, create list of such objects before while loop:

qlist<historyitem*> innerresult; while (queryinner.next()) {       /* snip */       historyitem* item = new historyitem();       item.channelid = channelidinner;       /* more lines ommited */       innerresult.append(historyitem); } emit historyloaded(innerresult); 

obviously, need matching signal definition in worker class:

q_signal void historyloaded(qlist<historyitem*> result);     

also noted in comments, have start background thread qthread::start().


Comments

Popular posts from this blog

ruby on rails - RuntimeError: Circular dependency detected while autoloading constant - ActiveAdmin.register Role -

c++ - OpenMP unpredictable overhead -

javascript - Wordpress slider, not displayed 100% width -