Finns det något bra sätt att fördröja ett trådmeddelande i Win32? Spånar fritt: >Du har ett antal meddelanden du vill skicka, men de får gärna komma med ganska stora mellanrum? <b>>Det jag skulle kunna göra är ju att skapa en tråd med en meddelandeloop vilket skulle ta bort trådskapandet men context switcharna finns ju kvar. </b> Ytterligare en variant: Måste den uttryckligen säga att den har ny information? Det räcker inte med en variabel som gui:t kan kolla av lite då och då? Jag håller med föregående talare, och tycker att det är dålig design att arbetstråden skall driva GUI:s uppdateringar. Hmm, jo, det är klart. Jag kanske skulle ha läst litet noggrannare innan jag uttalade mig. Ursäkta. >Varför skapa en ny tråd (fördröjd) i GUI:t? Varför inte bara ha en timer som genererar en event var I [Threading problem] så finns en motsvarande tråd om WinForms och C# (se Patrik Löwendahls inlägg en bit ner samt kommentarer om [Begin/End]Invoke), och jag skulle vilja påstå att problematiken är samma i C++ med MFC.Fördröja meddelande
Bakgrunden är att jag har en tråd som utför ett jobb och som jag vill skall uppdatera GUI med hur det går. Eftersom jobbtråden skapar en massa meddelanden vill jag inte att GUI:et skall uppdateras hela tiden utan några gånger i sekunden räcker.
För närvarande har jag en funktion "DelayMsg" som skickar ett meddelande med fördröjning genom att skapa en ny tråd som gör Sleep() och sen skickar meddelandet.
Det fungerar bra men när jag körde profilern visade det sig att oväntat mycket tid spenderas i DelayMsg funktionen.
Verkar alltså inte vara någon bra idé att skapa en ny tråd varje gång jag skall skicka meddelande.Sv: Fördröja meddelande
Du har ett antal meddelanden du vill skicka, men de får gärna komma med ganska stora mellanrum?
Borde du inte i princip kunna skriva till nån buffer, och sen ha en enda tråd som bara ligger och väntar på på att få lov att skicka?
Eller om du skriver meddelanden direkt till en buffert, och låter GUIt få timer-meddelanden så fort den får läsa från bufferten?Sv:Fördröja meddelande
Nja inte riktigt. Jag har en statusbar i GUI:et som visar jobbtrådens status typ "X poster behandlade". Jobbtråden skapar texterna som skall skrivas och skickar sedan dem till GUI tråden som uppdaterar statusbaren. Problemet är att jobbtråden går med lägre prioritet än GUI tråden så varje meddelande till GUI tråden genererar en context switch bara för att uppdatera statusbaren. Eftersom det kan vara 1000 poster i sekunden som behandlas blir hela applikationen seg eftersom jobbtråden bara behandlar en post mellan varje context switch och GUI tråden måste behandla 1000 meddelanden i sekunden.
Därför gör jag så här:
1. Lagra texten i en buffer
2. Om bufferten var tom innan skicka ett fördröjt (t.ex. 100ms) meddelande till GUI:et
3. När GUI:et får meddelandet skriver det texten i statusbaren och tömmer bufferten
(självklart finns det en semafor med också)
På detta sätt kan jag frikoppla både jobbtråden och GUI tråden från att bry sig om hastigheten på meddelandena.
>Borde du inte i princip kunna skriva till nån buffer, och sen ha en enda tråd som bara ligger och väntar på på att få lov >att skicka?
Jo det är ju det jag gör men hur fixar jag "bara ligger och väntar" på nåt smart sätt. Just nu skapar jag en tråd som bara gör:
Sleep();
PostMsg();
och sen avslutas tråden.
Problemet är på detta vis skapas en ny tråd 10ggr i sekunden och dessutom blir det ju 2 context switches varje gång (en för att starta tråden vilken bara anropar Sleep och sen tillbaka till jobbtråden).
Det jag skulle kunna göra är ju att skapa en tråd med en meddelandeloop vilket skulle ta bort trådskapandet men context switcharna finns ju kvar.Sv: Fördröja meddelande
Jepp, det var en meddelandeloop jag tänkte. Du skulle ju kunna testa om du får någon prestandavinst, iaf.
Annars tänkte jag flera ideer nu när jag har skrivit detta, men ingen av dem har vid närmare eftertanke funkat... du kanske får ett uppslag.
1. Ange tiden sen senaste uppdatering i samband med skrivning till bufferten. Funkar ju inte om du ex. får en "väldigt långsam post".
2. Skicka meddelanden till GUIet på något smartare sätt. Men det går ju inte, för det spelar ju ingen roll att det är något smart meddelande, det kommer ju gå åt precis lika mycket tid.
3. Ta vart n:te meddelande. Faller direkt.
Det man då skulle kunna göra är att göra en kombination med 1:an eller 3:an, men ha någon form av prediktion på tidsåtkomsten. Fast då är frågan om det tar längre tid att göra själva uppskattningen än tidsvinsten kan väga upp.Sv:Fördröja meddelande
Sv: Fördröja meddelande
Det är betydligt bättre (speciellt om du senare har flera arbetstrådar, säg 10 stycken) att GUI:t har en timer som går med jämna mellanrum och kollar av arbetstrådarnas status (som i sin tur är trådsäkrade).
Dessutom är det ju ingen poäng med att uppdatera GUI:t 1000 ggr per sekund (och abretstråd). Ingen kommer ju att se det ändå. 10 ggr per sekund totalt brukar räcka bra.
Dessutom finns det en risk för att man stryper arbetstråden då man lägger all CPU på att uppdatera GUI:t.
/AndreasSv: Fördröja meddelande
Men det är inte riktigt det han försöker att uppnå (tror jag).
Varför skapa en ny tråd (fördröjd) i GUI:t? Varför inte bara ha en timer som genererar en event var 100:e ms eller liknande? Och i timerns handler så kollar man av status på alla arbetstrådar.
Vad tillför en ny tråd?
Min erfarenhet (iofs mest MFC) är att trådar och GUI är livsfarligt ihop i C++. MFC tycker inte om trådar särskilt mycket alls. Därför bör man ha arbetstrådar som har statusinfo som kollas av av GUI:t (t.ex via timer-events). GUI-tråden skall driva GUI:t. Annars kan man få problem, speciellt när det börjar bli tajt om CPU-tid.
/AndreasSv:Fördröja meddelande
>100:e ms eller liknande? Och i timerns handler så kollar man av status på alla arbetstrådar.
Självklart, tyckte bara att det vore bättre om arbetstrådar och andra fönster berättade själva när de hade hade nåt att meddela.
>Vad tillför en ny tråd?
Ingenting, det var ju det jag också tyckte. Den nya tråden finns ju bara för att kunna fördröja meddelandet.
>Min erfarenhet (iofs mest MFC) är att trådar och GUI är livsfarligt ihop i C++. MFC tycker inte om trådar
>särskilt mycket alls
Förstår inte vad du menar. Att kombinera trådar och globala resurser (t.ex. GUI, globala variabler) är väl alltid svårt oavsett ramverk och programspråk. Problemet brukar oftast vara att dokumentationen inte berättar vilka globala resurser olika funktioner använder.
Kan inte påstå att jag har haft några problem med tråding i MFC.Sv: Fördröja meddelande
Du kan se i http://www.mvps.org/vcfaq/mfc/11.htm och http://www.mvps.org/vcfaq/mfc/12.htm vad en MVP säger om trådar och MFC. Framför allt den första är han slår fast att anrop in i MFC fån en arbetstråd kan gee asserts.
Jag har personligen en hel del erfarenhet av multitrådade applikationer och MFC och tyckte att man oftast fick problem om man lät någon anna tråd än GUI-tråden (dvs huvudtråden i programmet) uppdatera GUI:t. Det blir ännu mera spännande om du har ActiveX-kontroller i ditt GUI som uppdateras från en anna tråd. COM och trådar är en riktig "can of worms". Men som sagt, det är min högt personliga åsikt.
Men tillbaka till huvudproblemet:
Att låta arbetstrådar tala om för GUI:t när de har något att meddela "känns bättre", det håller jag med om. Haken är att det inte fungerar så bra i praktiken. Framförallt så skalar det inte om du har flera arbetstrådar.
Mitt råd: använd timer i GUI:t som pollar av arbetstrådarnas status/meddelanden. Take it or leave it. :-).
/Andreas
/Andreas