Senkronize olmayan programlamada, "wait for", bir anti-pattern olarak kabul edilir. Bir şeyleri beklemek yerine, yerine getirilmek üzere bir koşula tepki vermek için kodu tasarlayın. Örneğin, kodu bir sinyale bağlayın.
Bunu gerçekleştirmenin bir yolu, eylemlerinizi ayrı durumlara bölmek ve her bir durum girildiğinde bazı işlemler yapmaktır. Tabii ki iş miktarı önemsiz ise, bir şeyler okunabilir tutmak için lambda yerine ayrı bir yuva kullanın.
Açık bellek yönetiminin olmadığını unutmayın. Qt sınıflarına sahip olmak için işaretçi kullanma, zamanından önce bir optimizasyon ve gereksiz yere kaçınılmalıdır. Nesneler, Worker
'un (veya onun PIMPL) doğrudan üyeleri olabilir.
Alt nesneler, tümünde Worker
kökünde sahiplik hiyerarşisinin bir parçası olmalıdır. Bu şekilde, Worker
örneğini başka bir iş parçacığına güvenli bir şekilde taşıyabilirsiniz ve kullandığı nesneler onu izleyecektir. Tabii ki Worker
'u doğru iş parçacığına da uygulayabilirsiniz - bunun için basit bir idiom var. İş parçacığının olay çalışanının işçiye sahip olması, böylece iş parçacığı olay döngüsü sonlandırıldığında (yani, QThread::quit()
numaralı telefonu çağırdıktan sonra), çalışan otomatik olarak elden çıkarılır ve hiçbir kaynak sızmaz.
template <typename Obj>
void instantiateInThread(QThread * thread) {
Q_ASSERT(thread);
QObject * dispatcher = thread->eventDispatcher();
Q_ASSERT(dispatcher); // the thread must have an event loop
QTimer::singleShot(0, dispatcher, [dispatcher](){
// this happens in the given thread
new Obj(dispatcher);
});
}
İşçi uygulaması: Sonra
class Worker : public QObject {
Q_OBJECT
QSslSocket sslSocket;
QTimer timer;
QStateMachine machine;
QState s1, s2, s3;
Q_SIGNAL void finished();
public:
explicit Worker(QObject * parent = {}) : QObject(parent),
sslSocket(this), timer(this), machine(this),
s1(&machine), s2(&machine), s3(&machine) {
timer.setSingleShot(true);
s1.addTransition(&sslSocket, SIGNAL(encrypted()), &s2);
s1.addTransition(&timer, SIGNAL(timeout()), &s3);
connect(&s1, &QState::entered, [this]{
// connect the socket here
...
timer.start(10000);
});
connect(&s2, &QState::entered, [this]{
// other_things here
...
// end other_things
emit finished();
});
machine.setInitialState(&s1);
machine.start();
}
};
: QThread::started()
bağlanırken açık saçık olacağını
void waitForEventDispatcher(QThread * thread) {
while (thread->isRunning() && !thread->eventDispatcher())
QThread::yieldCurrentThread();
}
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
struct _ : QThread { ~Thread() { quit(); wait(); } thread;
thread.start();
waitForEventDispatcher(&thread);
instantiateInThread<Worker>(&myThread);
...
return app.exec();
}
Not: Etkinlik memuru QThread::run()
içinde bazı kod kadar yok yürütme şansı vardı. Bu nedenle, iş parçacığının üreterek oraya ulaşmasını beklemek zorundayız - bu, çalışan iş parçacığının bir ya da iki verim içinde yeterince ilerlemesi için büyük bir olasılıktır. Böylece zaman kaybetmeyecek.
Çok iyi bir fikir paylaşmaya karar verdik. Test ettim (koduma ve amacımla uyumlu bazı değişikliklerle) ve işe yarıyor. Tabii ki oy kullandım :) –