Thread design recommendation [SOLVED]
-
I wouldn't bother with a thread pool. I don't think (based on what you said) that you are doing enough to need multiple threads per device. Unless I misunderstood that part.
The Qt threading stuff will work great for your needs.
Qt signals/slots would probably handle things just fine. But you said some places are slow communications in which case without a thread you would lock up the GUI.
You can basically have an object you assign to a QThread. That objects can have signals/slots attached to it. This will handle your threading automatically. Then you can just do something like emit myStartSignal(); and setup a handler to catch the return signal of somethingDone(). So your threaded object would emit somethingDone() when the task was complete. And you register to catch that signal on a slot where you need it. Something like:
@
connect(myThreadObject, SIGNAL(somethingDone()), this, SLOT(myProcessSlot()));
@Basically it sounds like Qt handles everything you need in a very easy manner.
-
That is my feel so far as well. Thanks ambershark for the reply!
My current design thought is something like:
Fixture
USB worker object/thread
Serial worker object/thread
Serial worker object/thread
Serial worker object/thread
Serial worker object/threadSo my app (and other potential clients) would interact with fixture. Fixture would handle the logic and sequencing needed to run the device and would have data/methods so my app and others can know what is happening, the status of devices, temps, etc.
Obviously there will be signals/slots between the workers and fixture. Then fixture will have some signals it can emit to notify watchers of things. Fixture would also have some methods to call like Init() might coordinate the process of setting the instrument up.
Some of my serial devices are RFID reader/writers so I'd imagine that fixture would have some methods like: WriteTag() which would know how to signal the worker/thread for the correct serial device to write the tag etc.
Anyway I'm going to mock up a prototype of this with some of the threads responding with some dummy data for now just to see how it all feels.
One question I have is who owns what? IE I'm going to need 4 QSerialPorts. Are they constructed and owned by my fixture or should the worker objects that deal with them construct and own them?
I'm sure some of this will come more clear as I bump into the various issues.
Thanks again for the reply.
-
The serial ports would be in your thread object. Any thing created or parented to the thread object will be on that thread's message loop.
You want to keep worker thread stuff off your main thread.
For instance if you had:
@
class MyObject : public QObject
{
Q_OBJECTpublic:
MyObject(QObject *parent = 0) : QObject(parent) { }signals:
void resultReady();private slots:
void myResult();
};// ...
QThread *thread = new QThread(this);
MyObject *obj = new MyObject();
obj->moveToThread(thread);
thread->start();connect(this, SIGNAL(doSomething()), obj, SLOT(startSomething()));
connect(obj, SIGNAL(resultReady()), this, SLOT(myResult()));emit doSomething();
@Using that example myResult() would be called when the result of the thread running happened.
It can be a lot more powerful than this. You can subclass QThread but this is just a simple example to get you started on threading. The part after the // ... comment is in another QObject based (so derived from any Qt class pretty much) class. It should have a doSomething() signal.
-
[quote author="ambershark" date="1420501306"]The serial ports would be in your thread object. Any thing created or parented to the thread object will be on that thread's message loop.
You want to keep worker thread stuff off your main thread.
[/quote]I generally understand all of that. But I want to make sure I understand the serial port owner. I was thinking it would be the worker object so something like:
@class MyWorkerObj : Object
{
private
QSerialPort serPort;.... with work function etc....
}@Then in controller or fixture like you have it basically:
@QThread *thread = new QThread(this);
MyWorkerObj *obj = new MyWorkerObj();
obj->moveToThread(thread);
thread->start();connect(this, SIGNAL(doSomething()), obj, SLOT(startSomething()));
connect(obj, SIGNAL(resultReady()), this, SLOT(myResult()));
@Then when MyWorkerObj runs its work method or is created perhaps it would setup the serial port and then use it of course.
Am I following what you mean correctly?
-
That would only work if you make QSerialPort serPort a pointer and allocate it after the MyWorkerObj is moved to the thread.
So:
@
class MyWorkObject : public QObject
{
private:
QSerialPort *serPort;
};void MyWorkerObj::startSomething()
{
if (serPort)
{
serPort->deleteLater();
serPort = 0;
}serPort = new QSerialPort(this);
}
@That would ensure that serPort is part of the QThread *thread you moved MyWorkerObj in to.
EDIT: oh and startSomething() is a bad place for overall initialization of variables. I would pick a different signal or I think QThread::start() emits something you can use. Can't remember off the top of my head.
-
No problem, happy to help.
You made a great choice with Qt. Been using it for 15 years now and it's just awesome.
Every time I have to do a project no matter how small without Qt I get grumpy cause I know it's just gonna be harder and a lot more work. :)
-
15 years... Nice! Well I have a long history with Borland/Embarcadero products and my client really wanted this in C++ Builder but frankly the support is just not there. Few if any active forums and the compiler seems out of date.
While they have some cool things I just couldn't feel comfortable that code written specifically over that platform would be well received when I finally hand it over to the client (which I must do as part of this work).
I think Qt is popular enough, supported well enough that my client will be extremely happy to receive it based on this framework.
One last question regarding your Edit. I agree that startSomething() is really not the best place to initialize vars. Why not the constructor of MyWorkerObj?
-
The constructor won't work because the object is constructed in the main thread before it is passed off to the qthread with moveToThread.
So you'll need a signal to init once the thread is started.