[C++ + QT] multi threaded applicatie

Pagina: 1
Acties:

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
Ik heb een multi-threaded applicatie. waarbij een thread is geconnect op een database. Maar als ik de gegevens uit de database wil refreshen dan moet ik als ik dit heb gedaan eerst met de muiscursor bewegen voordat het in de listview die ik hiervoor gebruikt komt te staan. is dit te voorkomen of is dit een bug in QT of iets anders.

Ik hoop dat duidelijk is wat mijn probleem is.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 10:15

curry684

left part of the evil twins

phpfreak-------- schreef op 05 december 2002 @ 20:54:
Ik hoop dat duidelijk is wat mijn probleem is.
Nee, je vergeet namelijk te vermelden op welk platform je bezig bent en op welke manier (componenten/API's) je aan de database connect. Tevens zou voorbeeldcode helpen over hoe je afhandelt dat de DB-thread een refresh van de listview forceert want daar zijn ook tientallen al of niet krakende mechanismes voor te bedenken.

Professionele website nodig?


  • GAEvakYD
  • Registratie: Juni 2001
  • Laatst online: 12:37
Ik zou in iedergeval je applicatie de kans geven de status-updates
af te handelen. Dat kun je doen door processEvents() (memberfunctie van Q- of KApplication object.
Deze stuurt events naar je messagequeue.

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
Ik gebruik QT op het platform linux.
Ik heb wel voorbeeld-code die geen gebruik maakt van een database en ik heb iets verkeerd gemeld. ik heb aangegeven dat de database-verbinding in een thread gebeurt. maar dit is niet het geval alleen de gegevens uit de database-verbinding worden gedaan in de thread. Ik heb even een kort vb. waarin duidelijk wordt gemaakt hoe ik de gegevens refresh en in de listview zet hierbij wordt geen gebruik gemaakt van de database.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "main.h"

TestWidget::TestWidget(QWidget *parent, const char *name) : QWidget( parent, name ) {
  lijst=new QListView(this);
  lijst->addColumn("eerste");
  lijst->setGeometry(0, 0, 200, 200);
//  this->show();
  deelprog=new testthread(lijst);
  deelprog->start();
  deelprog->wait();  // dit wel of niet maakt geen verschil ik heb het in de database-file er niet instaan
}
testthread::testthread(QListView *lijst2) {
  lijst=lijst2;
}
void testthread::run(void) {
  sleep(1);
  (void)new QListViewItem(lijst, "eerste");
}

includes in main.h
C++:
1
2
3
4
5
#include <qt.h>
#include <qapplication.h>
#include <qpushbutton.h>
#include <qlistview.h>
#include <qthread.h>

het geheel werkt wel maar met hetzelfde probleem als met de database
in main.h staan de classedefinities en in main.cpp wordt het geheel aangeroepen. als dat nodig is wil ik dat ook nog wel posten.

[ Voor 10% gewijzigd door Shadowman op 06-12-2002 16:50 . Reden: commentaar vergeten ]


  • Shadowman
  • Registratie: Januari 2002
  • Niet online
geeft de thread niet een signal dat het klaar is. als het dit geeft krijg ik de rest wel voor elkaar maar ik weet niet welk signal dat moet zijn.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 10:15

curry684

left part of the evil twins

Sja van mij geen antwoord omdat ik in QT noch Linux echt thuis ben :) Ik denk echter dat je onder Linux ook wel met Event objects kunt werken, dat heb je hier namelijk nodig. Dan gaat thread A in kernelmode wait totdat het Event object gezet is, en vervolgens pulset thread B het event.

Maja je zult dus even op een Linux goeroe daarvoor moet wachten :P

Professionele website nodig?


Verwijderd

De reden ken ik. Je gebruikt linux+Qt en dus X. De thread die de dingen uit de database haalt is niet de X thread. De X thread zit in de main loop, luistert naar een socket en blockt dus, terwijl de database druk bezig is. De X thread heeft dus geen flauw idee wanneer dat klaar is, en blijft dus blocken, totdat er iets uit die socket komt, bv. een MousemotionEvent. Dan refresht Qt alles. Je kunt dit zelf versnellen door een fake event te sturen of door actief een redraw te doen in die thread, maar dan zal het crashen omdat X single threaded is (ugh!).

Een oplossing weet ik niet, maar dan weet je dus in elk geval waarom het blockt totdat je de muis beweegt.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-04 03:50
Als het probleem is dat je X thread blijft wachten, kun je die dan geen signal sturen? Dan zou de boel ook ververst moeten worden, lijkt me. Ik moet echter zeggen dat ik geen uitgebreide kennis van X of QT heb, dus het is een wilde gok.

Verwijderd

Wat ik ervan begrijp is het volgende: de socket heeft een protocol, en als twee threads dezelfde socket gebruiken (dezelfde X sessie dus), dan komen er twee object streams 'door elkaar', waardoor de socket niet meer goed werkt -> crash (X async error). Een signal vanuit X gaat echter ook via die socket, en moet dus ook vanuit die X thread gebeuren, anders crasht ie alsnog. Best wel bout dus eigenlijk... Je moet dus de listen @ die socket onderbreken, daar is een functie voor in X, maar ik weer niet uit mijn hoofd welke.

Ik zal eens naar documentatie zoeken hierover, misschien vind ik wel iets zinnigs.

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
*KICK*

Beelzebubu heeft gelijk dat de hoofd thread niet weet wanneer de onderliggende klaar is. Ik heb nl. eventjes geprobeerd om als id de inhoud had gerefreshed de netwerk-kabel eruit te trekken (voordat er iets in de listview stond) en als ik dan met de muis bewoog kwam het er wel in de listview te staan.

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
*KICK*

ik heb dat signal voor elkaar maar hoe moet ik die main-loop nou wakker schudden

Verwijderd

Ik weet daar geen nette oplossing voor... :{. Daarvoor werk ik te weinig met Qt. ;(.

Wat je eventueel kan proberen [mode=vieze_hacks], is om een recurring timeout van 1 second (bv.) in de main thread te doen, waarbij dus elke seconde een wake-up van de listen-to-socket() van X gebeurt. Onder Gtk/Glib gebeurt dit met g_timeout_add(), Qt zal daar ook wel een functie voor hebben... Deze functie checkt dan elke seconde of er een redraw moet gebeuren omdat de data compleet is, en zo ja, dan sluit ie de timout af (dan moet je in de Qt documentatie ff doorzoeken hoe dat moet, in Gtk+/Glib return't de functie die je in g_timeout_add() geeft TRUE om de timeout niet te verwijderen, of FALSE om 'em wel te verwijderen).

Het is hacky, maar wel het makkelijkste wat ik kan bedenken... Er moet ook een nette manier zijn, maar daar kan ik niet zo snel opkomen... :{. Als ik d'r ooit achterkom, zal ik 't hier nog wel toevoegen als addendum.

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
dit werkt bijna goed:
ik neem aan dat je dit ongeveer bedoelt
C++:
1
2
this->hide();
this->show();

alleen hierbij knippert het scherm of verdwijnt de hele applicatie totdat je over de taakbalk gaat. dit is in iedergeval niet de bedoeling.
Of nog erger de applicatie knalt er helemaal uit met deze error:
code:
1
2
Xlib: unexpected async reply (sequence 0x364)!
(en andere sequences zoals: 0x5d9, 0x187, 0x298, enz)

* Shadowman hoopt dat iemand hier iets op weet

[ Voor 7% gewijzigd door Shadowman op 17-12-2002 20:50 ]


Verwijderd

Sorry als ik veel onzin praat nu ;-) Want heb niet alles gelezen, maar je kan prima signalen emitten naar alle qobject's .. Das de enige manier imho.

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
Verwijderd schreef op 18 december 2002 @ 12:24:
Sorry als ik veel onzin praat nu ;-) Want heb niet alles gelezen, maar je kan prima signalen emitten naar alle qobject's .. Das de enige manier imho.
het emitten van de signalen lukt mij wel en ook naar alle objecten maar ik wil de main-thread wakker zien te krijgen zodat er refresh op de listview wordt gedaan en dat je dat ook ziet.

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
*KICK*
edit:
Is al gelukt (zal het er ff bij zetten zodat de oplossing in iedergeval bekend is:P):
C++:
1
connect(qApp, SIGNAL( guiThreadAwake()), this, SLOT(opstaan()));

en in het SLOT opstaan():
C++:
1
qApp->wakeUpGuiThread();

[ Voor 96% gewijzigd door Shadowman op 25-12-2002 19:37 . Reden: oplossing erbij zetten zonder te kicken ]

Pagina: 1