[Qt-interest] BlockingQueuedConnection where and how to ?!
Mihail Naydenov
mlists at ymail.com
Wed Dec 2 19:22:03 CET 2009
----- Original Message ----
> From: BRM <bm_witness at yahoo.com>
> To: Mihail Naydenov <mlists at ymail.com>; qt-interest at trolltech.com
> Sent: Wed, December 2, 2009 7:18:26 PM
> Subject: Re: [Qt-interest] BlockingQueuedConnection where and how to ?!
>
> I would highly suggest you look at what the worker thread is actually receiving,
> and I suspect you are doing something quite dangerous with your signal.
> The selection you do gets a list of pointers to items in the GUI. This is likely
> causing your crash as operations on the GUI (add/remove/move/etc.) will change
> the contents of the list without notifying the worker thread.
>
> I'd highly suggest storing the actual data in a thread sharable container that
> is linked to the GUI for display purposes only; but can be accessed by the
> worker threads safely.
> This gives you control of how the data is added/removed/etc - and by making your
> container a QObject derived class, you could even take advantage of
> signals/slots for each stored item
> so worker threads could (a) use a thread sharable container to access - e.g.
> QSharedPointer - and (b) be notified of changes in the data.
>
> Even making your list a list of QPointers would be of benefit since that at
> least gets notified when the pointer goes away; but you'll still need to convert
> to a thread sharable container for the data.
>
> $0.02
>
> Ben
Thank You, for your advises, they make sense indeed.
However, all this sending of pointers to ui elements was just for the (stupid) test, in the real project I send just a list of strings, no pointers, no ui.
Still the test should work, because I dont modify the list in any way, also the crash should be on/after modification.
Also, as I said, the "work" is fake loop returning an int, no pointers, no shared data.
Anyway, I modified the sample to send a dummy list of ints, and attaching it below.
(the results ware exactly the same. On my 4 core machine, if I dont use blocking, it crashes within few seconds, sometimes longer - few minutes -
every time, guaranteed!)
------------------------------------
#include <QtGui>
// lame work doing function
int work(int item)
{
int timespend = qrand();
int result = 0;
for(int i=0; i < timespend*2; i++)
result = i;
return result;
}
class view : public QListWidget
{
Q_OBJECT
public:
view(QWidget* parent=0) : QListWidget(parent)
{
connect(this, SIGNAL(itemSelectionChanged()), SLOT(onitemSelectionChanged()));
for(int i=0; i < 1000; i++)
{
insertItem(i, new QListWidgetItem("item_" + QString::number(i)));
}
startTimer(0);
}
void timerEvent (QTimerEvent* e)
{
clearSelection();
killTimer(e->timerId());
// select randomly some items
QItemSelection selection;
int rowL = qrand();
int max = model()->rowCount() - 1;
if(max < 0)
max = 0;
while (rowL > max )
{
rowL = qrand();
}
int rowR = qrand();
while (rowR > max )
{
rowR = qrand();
}
if(rowR > rowL)
qSwap(rowR, rowL);
selection.select(model()->index(rowR, 0), model()->index(rowL, 0));
selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
// every 0 to 1500 ms we will submit another job
int timeout = qrand();
while (timeout > 1500 )
{
timeout = qrand();
}
startTimer(timeout);
}
signals:
void needWorkdone(const QVector<int>& items);
private slots:
void onitemSelectionChanged ()
{
QVector<int> dummy(selectedItems().count());
emit needWorkdone(dummy);
}
};
// a worker (living in another thread)
class worker : public QObject
{
Q_OBJECT
public:
worker(QObject* parent=0)
{
// for simplicity the work result is handled in the worker
connect(&_workWatcher, SIGNAL(resultReadyAt(int)), SLOT(workdoneAt(int)));
}
~worker() { _workWatcher.cancel(), _workWatcher.waitForFinished(); }
public slots:
void dowork(const QVector<int>& items)
{
if(!items.isEmpty())
{
if(_workWatcher.isRunning())
{
_workWatcher.cancel();
_workWatcher.waitForFinished();
}
qDebug()<<"work on";
_workWatcher.setFuture(QtConcurrent::mapped(items, work));
}
}
void workdoneAt(int at)
{
qDebug()<<"ready at"<<at;
int result = 0;
// >>> commenting this line will (also) avoid the crash <<<
result = _workWatcher.resultAt(at);
qDebug()<<"result: "<<result;
}
private:
QFutureWatcher<int> _workWatcher;
};
#include "main.moc"
Q_DECLARE_METATYPE(QVector<int>)
// just because I am using Eclipse
#include <iostream>
void myMessageOutput(QtMsgType type, const char *msg)
{
std::cout << msg << std::endl;
}
int main(int argc, char *argv[])
{
qInstallMsgHandler(myMessageOutput);
qRegisterMetaType< QVector<int> >();
QApplication a(argc, argv);
QThread th;
th.connect(&a, SIGNAL(aboutToQuit()), SLOT(quit()));
worker w;
w.moveToThread(&th);
th.start();
view v;
w.connect(&v, SIGNAL(needWorkdone(const QVector<int>&)), SLOT(dowork(const QVector<int>&))
//, Qt::BlockingQueuedConnection // uncommnet to avoid the crash, but block the ui.
);
v.show();
return a.exec();
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: main.cpp
Type: text/x-c
Size: 2985 bytes
Desc: not available
Url : http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20091202/4a49fe5a/attachment.bin
More information about the Qt-interest-old
mailing list