View Full Version : Tangled in QThreads

13th October 2009, 20:49
I have an issue similar to this link http://www.qtcentre.org/forum/f-qt-programming-2/t-qthread-trying-to-limit-threads-23606.html/?highlight=QThread

I have tried to use the QtConcurrent::run function but it seems something is still wrong.
What I have is a long operation that calculates points that go on a map (QImage or QPixmap). I want the result to be a point list (QPolygonF) such that I can call QPainter::drawPoints(const QPolygonF & points). Now this works fine when I have 1 set of data. I want to split the job and get it done quicker by using say 2 (or more) calls to QtConcurrent::run on a part of the data.
The idea is to call them one after the other then wait for all of them to be done. For each one that finishes I can draw that polygon to the map; and, when done I have the full map.
What happens is I get one of them to finish but am baffled as to how to wait for all of the functions to return. I tried sub classing QThread but it seems when one instance of the thread is called the other returns immediately. Can I only call one instance of a sub class of QThread at a time?

Will provide code if needed.

sw developer

13th October 2009, 21:15
QtConcurrent is supposed to be a higher level API that relieves you from having to work with QThread directly. How/why do you mix both?

Best show us some code, so we have a proper grounds for discussion.

13th October 2009, 22:01
Oh sorry, caduel, I have confused you. I first tried with QtConcurrent then I tried with QThread. Let me show you some code...

Here is the line that will call the function:


where myStruct is a bunch of data I need in the function.
defined as:

struct MidpointStruct {
QList<ShotGraphicsItem *> sgiList;
GeometryVersion *gvLocal;
int startIndex;
int size;
int decimateBy;
QImage image;
MidpointGraphicsLayer * mpgl;


ShotGraphicsItem and MidpointGraphicsLayer are types of QGraphicsItems,

declaration of function (it is a part of the class MidpointSceneThread):

QPolygonF MidpointSceneThread::getMidpoints(MidpointStruct &myStruct);

This function goes through the list of ShotGraphicsItems and does some calculations and returns a set of points (Midpoints) that I use to draw on a pixmap.

The issue is I want the list of ShotGraphicsItem to be broken up and I tried several things to get the future return items...

I tried making a loop and calling the run function 3 times...
More CODE:

for (int ndx = 0; ndx < numThreads; ++ndx){
QFuture<QPolygonF> midpoints[ndx] = QtConcurrent::run(this,&MidpointSceneThread::getMidpoints,myStruct[ndx]);

Is this even a proper way to split up the job? when I run this and call :

for (int ndx = 0; ndx < numThreads; ++ndx)
resultPoly[ndx] = midpoints[ndx].result();

I get the first one but the loop does not get the other 2 results and only part of the map is drawn.

I hope this makes it clearer what I'm asking.


14th October 2009, 08:53
have you had a look at QtConcurrent::mapped()?

14th October 2009, 18:32
I have but I am in the middle of looking at it again. QtConcurrent::mapped() or QtConcurrent::blockingMapped() should work better than QtConcurrent::run. I see (not from documentation but from reading this forum) that the map style function must take 1 argument. Does that mean there is no way to use a class member function (method) with this? Is there a way around this?


14th October 2009, 20:06
Thanks for the reference. After studying my code I found an error that caused only one of my threads to loop fully. After fixing this error now all threads complete. I also found out about
std::bind1st which allows me to use my member function with the concurrent Map function.
For all interested here is what I did:
function declaration:

QPolygonF MidpointSceneThread::partialDraw(MidpointStruct myStruct)
NOTE: You cannot use a reference type because of the bind function so I pass by value the struct 'myStruct'.

Then I call it like this:

QList<QPolygonF> polys = QtConcurrent::blockingMapped (structList,std::bind1st(std::mem_fun(&MidpointSceneThread::partialDraw),this));

when that returns I can use my List of polygons as I wish!!

Last question... is the use of std:bind1st not portable? I'm not familiar with some of the std:: functions.

sw developer

14th October 2009, 20:24
have a look at Boost.Bind if you want to pass a (bound) member function;
there should be some threads here on how to use it, search for "boost::bind"

14th October 2009, 23:00
Thanks I'll do that.