2016-12-16 1 views
0

Kurzbeschreibung der Umgebung: Ich habe ein Gerät, auf dem eine in qt geschriebene Anwendung ausgeführt wird. Es hat einen Haupt-Thread, der Datenbank-Operationen (SQlite) und einen separaten Thread für Netzwerk-Operationen (via 3G) behandelt. Hauptthread Ereignisschleife wird von QCoreApplication :: exec ausgeführt und der andere Thread, der Netzwerkvorgänge behandelt, wird von QThread :: exec ausgeführt. Btw, Socket-Thread-Affinität wird geändert, nachdem es gestartet wurde (z. B. moveToThread (socketThreadPtr))QTimer feuert spät, weil andere Threads mit großen Schleifen beschäftigt sind

Kurzbeschreibung des Problems: Main Thread ist in einer Schleife beschäftigt, um rund 10k Datensätze aus der Datenbank auswählen und diese Schleife dauert etwa + 30 Sekunden. Im Netzwerk-Thread gibt es einen 15-Sekunden-Timer, der bei jedem Ablauf eine Keep Alive-Nachricht senden muss. Das Problem ist, dass der Slot für das timeout() - Signal erst ausgeführt wird, nachdem die Schleife beendet ist.

Lösung bis jetzt gegründet (aber nicht befriedigend): Wenn ich QCoreApplication :: processEvents in der Schleife aufrufen, die die Datensätze auswählt, ist das Problem gelöst, aber ich frage mich, ob eine Lösung anstelle dieser Problemumgehung vorhanden ist.

Anmerkung: Der Timer, Signal und Slot, der den Befehl zum Senden der Keep Alive-Nachricht gibt, wird derzeit im Haupt-Thread behandelt (aber das Lesen/Schreiben geschieht im Netzwerk-Thread). Außerdem habe ich den Timer im Netzwerk-Thread verschoben, aber ich habe das gleiche Ergebnis wie im Haupt-Thread.

+0

Da der Zeitgeber netzwerkbezogenen es auf dem Netzwerk Gewinde sein soll. Stellen Sie sicher, dass der mit ihm verbundene Steckplatz sich in einem Objekt auch im Netzwerk befindet. –

+0

Der Timer lebt wahrscheinlich noch im Hauptthread. Erstens: Erstellen Sie den Socket direkt im Thread oder setzen Sie den Socketdescriptor und öffnen Sie den Socket mit einer QueuedConnection. Erstellen Sie den Zeitgeber im Konstruktor nicht und rufen Sie movetothread für das Objekt auf. Rufen Sie stattdessen eine Initialisierungsfunktion mit invokeMethod oder einer in einer Warteschlange stehenden Signal/Slot-Verbindung auf. In dieser Funktion erstellen Sie den Timer mit new. Sonst bleibt der Timer eigentlich im Hauptthread –

+0

Hallo Leute! Danke für die schnellen Antworten. Kevin, ich hatte den Timer komplett im Netzwerk-Thread verschoben, mit dem entsprechenden Slot im Netzwerk-Thread. Übrigens wurde der Timer auf dem Heap erstellt. – ionutCb

Antwort

1

Sie haben Timer in Ihrem Netzwerk Thread erstellen, vielleicht QTimer ist Teil des Netzwerk-Thread, so dass das Netzwerk-Thread in Hauptthread und Thread-Affinität seiner Kinder Satz Haupt-Thread aufgebaut sein, neben ihr Netzwerk bewegt haben Thread zu neuen Qthread, aber was ist mit Qtimer? es lebt immer noch im Hauptthread (außer wenn Sie die Netzwerkklasse explizit als übergeordnet definieren, so wie Sie gesagt haben, dass moveToThread sowohl die untergeordneten Objekte des Objekts als auch Qtimer betrifft)

Der Qtimer sollte im Netzwerk-Thread erstellt werden, Sie können ein neues erstellen Qtimer in einem der Netzwerk-Thread-Slots und verbinden Sie es mit dem Qthread :: start-Signal. Wenn Sie also die Startmethode von Qthrad aufrufen, wird Ihr Slot auf dem neuen Thread ausgeführt und Qtimer wird auf diesem Thread erstellt.

+0

Niemals über das gestartete Signal nachgedacht, nette Sache, wenn es ein dedizierter Thread zu diesem einen Objekt ist! –

+0

@SebastianLange kann es vielleicht mehr beschreiben? –

+1

Jahandar, weißt du was du bist? Ein toller Typ, der mich zur Lösung führt. Danke vielmals! Als Schlussfolgerung konstruierte ich den QTimer so: Neuer QTimer (0) im Konstruktor. Nachdem du mich nach der Affinität von QTimer gefragt hast, war es das. Also habe ich den QTimer auf diese Weise erstellt: new QTimer (this), dies ist der Eltern-Netzwerk-Thread. QTimer wird immer noch im Konstruktor konstruiert. moveToThread() ändert die Affinität der Objekte und ihrer untergeordneten Elemente. Der Kinderteil, den ich vermisst habe. Hoffe, ich war klar genug über die Lösung. Wenn nicht, bitte fragen Sie. – ionutCb

0

So etwas sollte eigentlich den Socket und den Timer in Ihrem dedizierten Thread erstellen, vorausgesetzt, Ihr Haupt-Thread ist der Server und Clients sollten in Threads behandelt werden. Ansonsten verwenden Sie einfach QTcpSocket::connectToHost() oder QTcpServer:::bind() in Ihrer Initialisierungsfunktion.

Mainthread:

auto t = new QThread(); 
t->start(); 
auto o = new MyThreadObject(); 
o.moveToThread(t); 
o.setDescriptor(socketDesc); 
QMetaObject::invokeMethod(o, "initialize", Qt::QueuedConnection); 

MyThreadObject:

class MyThreadObject : public QObject 
{ 
    Q_OBJECT 
public: 
    MyThreadObject(){...}; 
    void setDescriptor(qintptr socketdescriptor) 
    { 
    m_desc = socketdescriptor; 
    } 
public slots: 
    void initialize() 
    { 
    m_tcpSocket = new QTcpSocket(); 
    m_tcpSocket->setSocketDescriptor(m_desc); 
    //socket configuration 
    m_timer = new QTimer(); 
    //timer configuration 
    m_timer->start(); 
    } 
private: 
    QTcpSocket* m_tcpSocket; 
    QTimer* m_timer; 
    qintptr m_desc; 
} 
Verwandte Themen