Wie in der Dokumentation eindeutig angegeben, darf auf Qt GUI nur vom Haupt-Thread aus zugegriffen werden. Bei komplexen Anwendungen mit mehreren großen und stark beanspruchten Tabellen kann dies ein Engpass sein, allein schon wegen der vielen Berechnungen der Schriftgröße, die Qt gerne durchführt. Die einzige Alternative, die mir einfällt, ist Multitasking mit separaten Prozessen. Die Tabellen sind derzeit so schnell wie möglich, ein benutzerdefiniertes Modell, das direkt auf einen Cache abgebildet wird, der von einem anderen Thread mit dataChanged()-Aufrufen auf den konservativsten Satz von geänderten Zellen gefüttert wird. Ich habe bereits mit vTune profiliert, 70% der App-Zeit ist jetzt in Qt-Rendering-Code. Irgendwelche Vorschläge?
Antworten
Zu viele Anzeigen?Ich habe QT nicht benutzt, aber der Zugriff auf die GUI von nur einem Thread aus (dem GUI-Thread) ist in fast jeder GUI, die ich kenne, eine bekannte Sache. Ich habe 2 Lösungen für diesen Fall verwendet, von denen ich die erste bevorzuge:
1) Ihr Formular aktualisiert die grafische Benutzeroberfläche (in diesem Fall die Tabelle) in Zeitintervallen. Der Timer wird durch die Ereignisse des GUI-Threads aktiviert. Bei diesen Timer-Ereignissen lesen Sie die Daten aus globalen Variablen und aktualisieren Ihre Tabelle. Die globalen Variablen können von so vielen Threads aktualisiert werden, wie Sie möchten. Möglicherweise müssen Sie den Zugriff auf die globalen Variablen synchronisieren (z. B. mit Semaphoren).
2) In vielen GUI-APIs können Threads die GUI aktualisieren, indem sie dem GUI-Thread eine Funktion (oder ein Objekt) übergeben und ihn bitten, diese so schnell wie möglich in seinem Kontext auszuführen. Der aufrufende Thread blockiert unterdessen, bis die GUI die Aktion ausgeführt hat. Ich kann mich an drei solcher Funktionen erinnern - Invoke
, InvokeLater
von Java und C#, oder wx.CallAfter
von wxPython.
Wenn Ihre Tabelleneinträge und Methoden in mehreren Schritten durchgeführt werden, können Sie die QCoreApplication::processEvents() um die qt ui zwischen den Berechnungen zu aktualisieren. Eine andere Möglichkeit ist, alles in einem anderen Thread laufen zu lassen und Signale von diesem Thread auszusenden, wenn die Berechnungen abgeschlossen sind. Am Ende werden die Aktualisierungen auf der Benutzeroberfläche vom Hauptthread aus durchgeführt, aber asynchron. Um eine Verbindung zu einem Signal aus einem anderen Thread herzustellen, müssen Sie qRegisterMetaType<> .