[Qt-interest] Basic QThread question
Sean Harmer
sean.harmer at maps-technology.com
Wed May 19 10:13:13 CEST 2010
On Tuesday 18 May 2010 08:34:46 Phil wrote:
<snip>
> This is exactly what I'm doing but the hardware has many write functions
> besides a data reading function. I'm attempting to write to the hardware
> from the main thread which intermittently conflicts with the read from the
> DevicePoller thread. Precisely the simultaneous access condition that you
> mentioned above.
>
> > It is difficult to say which approach is better for you without knowing
> >
> > what Class_A actually does and how long the Class_A::getIntitialValues()
> > and getData() functions take. If possible I would go with the second
> > option as it removes the possibility of concurrency issues within
> > Class_A.
>
> Before receiving your reply Sean I was nearing the point of giving up on
> threads and going back to my GUI blocking version. It seems to me that I
> need to combine the hardware's write functions, which are currently
> members of the main class, and the read function into your DevicePoller
> class. I'm unsure just how I might access the write functions from the main
> class without causing a simultaneous access condition. The best that I come
> up with is:
>
> if(OkToRead)
> readDevice();
>
> > No problem. If you still run into trouble, come back with more details on
> > Class_A.
>
> I'm hesitant to burden the other list members with this seemingly never
> ending saga. I'll see if I can approach this problem from a different
> angle.
Right, the important piece of information that you missed out was that Class_A
is what actually communicates with your device and that both threads are
trying to do so.
If the communication with this device can potentially block, then I would move
the classA object into the thread and have all comms performed in the worker
thread. After all the DevicePoller class is simply a wrapper around a timer
and what I thought was going to be a few simple calls to talk to your device.
Just replace or augment the DevicePoller object with something that meets your
needs.
This way the polling timer will not cause a conflict because if you are in the
middle of communicating with your device in a blocking manner in the worker
thread, then the timer that triggers the polling will not fire until you
return to the event loop. You can easily pass information/requests to/from the
main main thread via the signal-slot mechanism.
The above method is essentially the blocking method that you had originally
but all the parts that can block are now in a worker thread rather than the
main GUI thread and so should be relatively simple to achieve.
Another thought, why do your communications to the device block at all? What
type of connection do you have to your device? Qt makes it easy to perform
non-blocking IO without the need for threads. We have similar objects that
perform such comms (using QextSerialPort or QTcpSocket) which do not block -
although we do move these objects into their own thread for other reasons.
This method sounds like it would be more work given the current blocking
design of your Class_A.
So in summary, two basic options:
(1) Move the one and only instance of Class_A into the worker thread and pass
info/requests to/from the main thread using signals/slots. Class_A does not
need to be changed and should be quite simple to do.
(2) Re-implement Class_A so that it uses non-blocking comms. More work but
potentially allows you to not need to use threads at all.
I would personally go for option (1) in the short term with a view to possibly
implementing option (2) later as this would for example allow you to
communicate with several devices from within the same thread without blocking
each other.
HTH,
Sean
More information about the Qt-interest-old
mailing list