[C++] UI updating, de juiste manier?

Pagina: 1
Acties:

  • ReverendBizarre
  • Registratie: December 2001
  • Laatst online: 24-03-2021
Ik ben bezig met een WTL programma wat op een verzameling files bewerkingen uitvoert. Dit kan enige tijd duren en in de tussentijd wil ik graag dat status dialog waarop onderandere een console (listbox met icoontjes) en een progress bar staan up-to-date blijft. Deze controls (CProgressBarCtrl en CListViewCtrl) zijn private members van mijn CDialogImpl derived class en hebben allebei een bijbehorende public method om hun status te updaten.

Tot nu toe heb ik voor dit probleem twee oplossingen kunnen bedenken.

1] stop het hele file processing gedeelte in een aparte worker thread (de mooiste maar ook ingewikkeldste oplossing)

2] laat het programma singlethreaded en geef het processing gedeelte een callback functie mee die om de zoveel tijd de controls op de status dialog update en dan CWindow::RedrawWindow() aanroept.

Mijn voorkeur gaat toch uit naar de eerste methode maar het probleem hier is dat ik erg weinig informatie kan vinden over hoe je nou vanuit een worker thread op een correcte manier met een UI thread communiceert. Op dit moment heb het zo dat de worker thread direct de methoden voor het updaten van de progressbar en console aanroept, maar volgens mij is dat niet de veiligste manier (alhoewel het in normaal gebruik goed lijkt te gaan). Dit heb ik al gelijk gemerkt toen ik in mijn dialog een cancel button wilde toevoegen die via WaitForSingleOjbect() wacht tot de thread klaar is (of in dit geval afgebroken wordt) voordat het dialog window verwijderd wordt (want de worker thread roept daar dus methoden van aan). Maar dat resulteert in een deadlock.

Mijn vraag is dus eigenlijk, wat is nou de correcte en veilige manier om vanuit een worker thread status updates door te geven aan een UI thread? Ik heb veel op Google gezocht maar ik kom weinig concreet nuttige resultaten tegen. Voornamelijk veel MFC multithreading tutorials met veel code en weinig uitleg.

Als iemand hier een antwoord op weet of misschien wat linkjes heeft naar nuttige multi-threading tutorials (in mijn ogen zijn nuttige tutorials dus voornamelijk uitleg en niet zo zeer lappen met code) hoor ik het graag.

  • ReverendBizarre
  • Registratie: December 2001
  • Laatst online: 24-03-2021
The juiste manier... ik ben lekker wakker zeg. :O

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
Je kunt met window messages veilig tussen threads communiceren. Vind je OO helemaal flex ? Dan bouw je er een C++ schil omheen.
IrishMaiden schreef op 04 september 2004 @ 01:21:
The juiste manier... ik ben lekker wakker zeg. :O
Haha, eigenlijk wel grappig :)

[ Voor 44% gewijzigd door farlane op 04-09-2004 01:56 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
IrishMaiden schreef op 04 september 2004 @ 01:19:
Mijn vraag is dus eigenlijk, wat is nou de correcte en veilige manier om vanuit een worker thread status updates door te geven aan een UI thread? Ik heb veel op Google gezocht maar ik kom weinig concreet nuttige resultaten tegen. Voornamelijk veel MFC multithreading tutorials met veel code en weinig uitleg.
Welke info moet je doorgeven aan je UI thread?
Je worker thread UI methodes laten oproepen is idd niet de mooiste manier...
Beter: je worker thread past de gegevens aan die je UI output bepalen,
en de UI past zichzelf dan aan op basis van deze gegevens.
Ipv je redraw methodes van je UI dus rechtstreeks op te roepen, verander je gewoon de gegevens die deze UI bepalen...
(Model-view-controller model, als dat je iets zegt...)
Maar 't hangt er dus wel erg vanaf welke en hoeveel info je moet doorgeven aan je UI ..

  • ReverendBizarre
  • Registratie: December 2001
  • Laatst online: 24-03-2021
Voor de progress bar is in principe alleen een integer nodig. Maar die console is een ander verhaal omdat daar gewoon een int (icoon imagelist index) en een string aan toegevoegd worden wanneer de worker thread wat zinnigs te melden heeft. Ik denk dat daarvoor de message optie dan beter is.

Ik zal er nog maar wat mee experimenteren dan.

[edit]

Ik heb het inmiddels geimplementeerd met messages en dat lijkt wel fijn te werken. Ik heb mijn eigen WM_USER+X messages gedefinieerd en die worden door de dialog window geprocessed die vervolgens de update methoden aanroept. Ik zat nog steeds ff met dat deadlocking probleem maar na even in de MSDN help zoeken kwam ik erachter dat SendMessage() op de message proc gaat wachten, wat natuurlijk niet meer werkt als die UI thread op de worker thread zit te wachten (nadat op cancel is gedrukt). PostMessage() lost dat probleem op.

[ Voor 45% gewijzigd door ReverendBizarre op 04-09-2004 17:15 ]


Verwijderd

Wat dacht je hier van: 3 klasses.
- Venster klasse
- Data klasse
- Worker thread klasse

De venster klasse reageert op user input. Krijgt refresh-bericht als de workerthreads weer wat gevonden hebben.

De data klasse werkt volgens subscription lijst patroon. Deze klasse maak je multi-thread-save bij ontwerp. Geeft update-berichten aan venster en worker threads (kan meer dan 1 worden ;)).
De data klasse houdt referentie telling bij en heft zichzelf op als deze op 0 komt. Let wel dat de refcount zowel vensters als workerthreads bevat.

De worker thread klasse zwoegt op zn opdracht en update het data object. Kan ook een cancel-berichtje ontvamngen van data klasse als de venster klasse dit aangeeft.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
IrishMaiden schreef op 04 september 2004 @ 16:18:
Ik heb het inmiddels geimplementeerd met messages en dat lijkt wel fijn te werken.
Je zou nog een intermediate object kunnen maken die een message-only window gebruikt en berichten verder stuurt naar objecten die zich daarop 'abonneren'. Is ook wel mooi OO ( zal vast ook een pattern zijn :) )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 07-04 13:41
farlane schreef op 05 september 2004 @ 00:41:
[...]
Je zou nog een intermediate object kunnen maken die een message-only window gebruikt en berichten verder stuurt naar objecten die zich daarop 'abonneren'. Is ook wel mooi OO ( zal vast ook een pattern zijn :) )
Observer?
Pagina: 1