QAbstractItemModel asserts & multithreading
-
Hey
I'm trying to solve a problem with these 2 aseserts :
###### FATAL: ASSERT: "last < rowCount(parent)" in file itemmodels\qabstractitemmodel.cpp, line 2782 (itemmodels\qabstractitemmodel.cpp:2782, (null)) ###### [34;1m ###### FATAL: ASSERT: "!this->isEmpty()" in file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qstack.h, line 62 (c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qstack.h:62, (null)) ######
I've recently moved a lot of my logic to thread and when I load data all that happens in thread now. I'm not sure how to bite it as all I got are these 2 crash lines and
The error does not happen in debug-Release mode, only in debug mode...
How can I bite it ?
Regards
Dariusz -
A model must be in the same thread as the view(s) - so it must be in the main thread. If this is not the case you must add QMutexes (or similar) to protect access from two different threads.
-
Yeah I've just dig in to it and found out the error location...
It was beginRemoveRows/endRemoveRows being called from another thread while QporxyModel/filterModel were trying to refresh/update data...
So I've learned that Q_EMIT beginRemoveRows() does not do what I though it did when it comes to signals..
The signal is being called from Thread & executed from thread... but I need to force it to main thread, how can I do this ?
Currently I'm thinking that I could do this >
QMetaObject::invokeMethod(qApp, [&]() { beginRemoveRows(index(),row,row);// + other code to finish the action... },Qt::BlockingQueuedConnection);
But does this not have a lot of overhead? How can I handle case like this?
Should I make my own signal/slot like
signal void beginRemoveRowsThreaded(Const QModelIndex&index, const int start, const int right end); slot inline void handleRemoveRowsThread(Const QModelIndex&index, const int start, const int right end){Q_EMIT beginRemoveRows(index.start,end);}
and do connection
connect(this,&item::beginRemoveRowsThreaded,this,&item::handleRemoveRowsThread,Qt::BlockingQueuedConnection);
and then call the internal signal to force it to main thread ? Will that be more efficient than the QMetaObject::invoke ?
TIA
-
I would send a signal to the model so it can fetch the new data from the thread - looks the easiest and cleanest solution for me - esp. since this will also work when the data fetching is not done in a separate thread, the logic will not change.
-
@Christian-Ehrlicher said in QAbstractItemModel asserts & multithreading:
I would send a signal to the model so it can fetch the new data from the thread - looks the easiest and cleanest solution for me - esp. since this will also work when the data fetching is not done in a separate thread, the logic will not change.
Hmmmmmmmmmm I'm lost :- D So do I disable some automatic fetching and then configure manual fetching? I'm lost o.O how do I do dis?
-
What to you mean with automatic/manual fetching?
-
@Christian-Ehrlicher
I would send a signal to the model so it can fetch the new data from the thread
Hmmm I think this might not work for me. Feels like I need it to work on per-item level. Essentially force any call changing child count to be main thread-based. -
@Dariusz said in QAbstractItemModel asserts & multithreading:
Hmmm I think this might not work for me
Why not? It makes no difference if you push or pull the data... but it's up to you :)