Arbeit so.)
Im Beispiel ist die Funktions-DLL in base und die Plugins in dylib*.
+
+Die getthingy Funktion in den Libs implementiert übrigens das "Factory-Pattern".
+Ja, so einfach können Buzzwords aussehen... ;-)
+
+Thread und Proxy
+-----------------
+
+Siehe main/thready.*
+
+Das Thread-Objekt ist so einfach wie möglich: nur eine Startroutine, die
+alle nötigen Parameter übernimmt und ein run(), welches das eigentliche
+Task-Objekt instantiiert.
+
+Die MyThread-Klasse ist dabei eine sog. Fasade oder ein Proxy. Die Arbeit
+wird von MyTask gemacht. Damit lässt sich in diesem Fall auch garantieren
+dass alle wichtigen Slots im richtigen Thread sind.
+
+Eine andere Variante den Thread zu implementieren, wäre den Konstruktor
+public zu machen, noch 0-viele setter für weitere Parameter und dann
+wird start()/run() aufgerufen...
+
+Wenn mit dem Thread kommuniziert werden muss dann benutzt man Signal-Slot-
+Kaskaden, siehe disruptThread()...
+
+QPointer
+--------
+
+...ist sehr praktisch wenn man ein QObject nicht besitzt oder es sich
+unvermittelt löschen kann. So wie unser Thread.
\ No newline at end of file
vl->addSpacing(10);
vl->addWidget(p=new QPushButton("Start Thread"));
connect(p,SIGNAL(clicked(bool)),this,SLOT(startThread()));
+ vl->addWidget(p=new QPushButton("Poke Thread"));
+ connect(p,SIGNAL(clicked(bool)),this,SLOT(pokeThread()));
}
void MainWin::startThread()
{
//start a thread and let it update the label automatically
- MyThread::startMe(mthingylabel,SLOT(setText(QString)));
+ mthread=MyThread::startMe(mthingylabel,SLOT(setText(QString)));
+}
+
+void MainWin::pokeThread()
+{
+ if(mthread.isNull())
+ mthingylabel->setText("Sorry, cannot poke a null thread");
+ else
+ mthread->disruptThread();
}
#include <QDialog>
#include "../base/thingy.h"
+#include <QPointer>
+class MyThread;
class QLabel;
class QLibrary;
void unloadLib();
///starts a thread to do stuff in the background
void startThread();
+ ///does funny things with the thread
+ void pokeThread();
///call that thingy from one of those libraries
void callThingy();
QLibrary*mthinglib;
//the thingy from that library
Thingy*mthingy;
+ QPointer<MyThread>mthread;
};
#endif
\ No newline at end of file
#include "thready.h"
#include <QTimer>
-void MyThread::startMe(QObject* c, const char* s)
+MyThread* MyThread::startMe(QObject* c, const char* s)
{
//create thread and remember connection to the outside world
MyThread *m=new MyThread(c,s);
//start it
m->start();
+ return m;
}
MyThread::MyThread(QObject* callee, const char* slot): QThread(callee)
//make sure it deletes itself
// Qt::AutoConnection effectively: Qt::DirectConnection - same object
connect(this,SIGNAL(finished()),this,SLOT(deleteLater()));
+ //initiate cascade
+ connect(this,SIGNAL(disruptThreadSignal()), &task,SLOT(disruptThread()), Qt::QueuedConnection);
//now loop for a while
exec();
}
//simply count up and tell everyone
emit updateString(QString("Hello, I'm a thread and can count to %1").arg(ctr++));
}
+
+void MyThread::disruptThread()
+{
+ emit disruptThreadSignal();
+}
+
+void MyTask::disruptThread()
+{
+ ctr+=1000;
+ gotime();
+}
///It does not know much about what is done there.
class MyThread:public QThread
{
+ Q_OBJECT
public:
///not needed, use startMe
MyThread()=delete;
///start the thread
///\param callee the object that gets the updated information, also owner of the thread object
///\param slot the slot to call for updates, must be SLOT(foo(QString)) or SLOT(foo())
- static void startMe(QObject*callee,const char*slot);
+ static MyThread* startMe(QObject*callee,const char*slot);
+ public slots:
+ void disruptThread();
+ signals:
+ void disruptThreadSignal();
protected:
///internal: creates the thread and remembers who to call
MyThread(QObject* callee,const char*slot);
private slots:
///called to update the thread status
void gotime();
+ ///called from cascade
+ void disruptThread();
signals:
///sent to the outside world when the thread has something to say
void updateString(QString);