30. juni 2000 - 14:36Der er
13 kommentarer og 2 løsninger
Så vent dog !
Jeg er ved at lave på er program hvor jeg skal ha' vist en ny form mens den gamle laver noget i baggrunden. Det er heller ikke noget problem !
MEN, lige efter den nye form bli'r vist går den gamle i gang med en hel hel masse som ta'r faktisk alt CPU kraften. Det vil sige, at den nye form når ikke at blive tegnet færdig før den gamle begynder på det den skal lave.
Kan man ikke på en eller anden måde lægge en delay(1000); ind som man kan i go'e gamle C++, så den når at tegne hele formen med den rigtige baggrundsfarve og de 2 labels der er på den inden den anden form går videre med det den skal ???
Snowball >> Tråde, tråde og atter tråde. Hvis du koede den tunge baggrunds process i en eller flere tråde var du ude over problemet. Ellers kan du kalden en refresh på din form der skal tegnes op fx. SplashScreen.Refresh;
Endelig var det nok værs at kigge på Application.ProcessMessages(); proceduren
jeg giver borisholt ret .. jeg tror dog du kan fixe det ligesom han sige ved at indsætte en application.processmessages; i dine loops hvor du udfører det meget processorkrævende arbejde.
Ilthrane: sleep er ikke nogen god løsning da det processorkrævende arbejde stadig skal ekserveres på et eller andet tidspunkt, og så vil det bare blokere for programmet i på et senere tidsrum .. derfor er processmessages en langt bedre løsning ..
Der ligger et eksempel med i delphi under ..\Borland\Delphi5\Demos\Threads den kan vise dig hvordan man bruger tråde/threads.
Dog vil jeg anbefale dig at afprøve processmessages først for jeg er ret sikker på at det vil virke ganske glimrende i dit tilfælde, husk dog på at du skal indsætte application.processmessages; hver gang der er et loop af en eller anden slags .. FOR/While etc. i den kode som er meget processorkrævende.
Tråd eksemplet i Delphi Stinker. De balnder en masse ting ind i det som ikke har noget med sagen at gøre ... Jeg har et simplet eksemple, hvis nogen ønsker det så send en mail til mig
application.processmessages skal man passe MEGET på, hvis man ikke har helt styr på hvad det gør - det kan nemlig give seriøse problemer. Brugeren kan fx. finde på at trykke på en knap som udfører det kode som du allerede er i gang med at udføre - POW, dødt program.
application.processmessages er fint nok i starten, men det holder ikke i længden. Belært af programmøren bag ICS (http://www.rtfm.be/fpiette/indexuk.htm), så er asynkron programmering meget mere effektiv end tråde. Jeg er i hvert fald holdt op med at bruge tråde.
lrj>> Du har ret, i dit eksempel kan det jo dog fixes ved at disable knappen og enable den til slut i koden igen, men det gælder jo selvfølgelig ikke altid ... fordelen ved processmessages er jo bare at det er en simpel løsning der som regel også virker til de fleste knapt så avancerede formål.
Men asynkron programmering lyder da ret spændende, er det noget som du ville have noget imod at forklare en lille smule om, altså hvad der gør det bedre end tråde ? Og har du evt. noget eksempelkode til at ligge som man kan se hvordan man skal bruge det udfra ?
Jeg tror faktisk ICS er det aller bedste eksempel.
Men det handler om at du du laver et objekt som har sin egen messagepump - ligesom application har det. Det er jo den du beder om at tømme sin kø når du kalder processmessages.
Normalt laver jeg et objekt som nedarver fra TComponent og som jeg så giver en public variabel af typen: FHandle: HWND; Desuden laver jeg en metode kaldet procedure WndProc(var MsgRec: TMessage); - det er den der er messagepumpen for objektet. Indholdet af denne procedure ses nedenfor.
Og i destroy bliver det så: DeallocateHWnd(FHandle);
Herefter skal du så have defineret hvilke messages dit objekt skal reagere på. Jeg har fx. defineret en metode kaldet procedure WMAutoDisconnectUser(var msg: TMessage); message WM_AUTODISCONNECT; - den hører til WM_AUTODISCONNECT, som jeg har defineret som Type WM_AUTODISCONNECT = WM_APP + 1;
Proceduren WMAutoDisconnectUser er defineret som: procedure TISPConControl.WMAutoDisconnectUser(var msg: TMessage); begin ...blah - gør noget med den vedsendte TMessage - her trækker jeg en henvisning til et objekt (pas forresten på med det, når det er asynkront. Er objektet gået ud af scope virker det ikke længere, og programmet dør...) assert(TObject(msg.WParam) is TOnlineUser); ...blah end;
Og her følger min WndProc så:
procedure TISPConControl.WndProc(var MsgRec: TMessage); begin with MsgRec do begin case Msg of WM_AUTODISCONNECT: WMAutoDisconnectUser(MsgRec); else Result := DefWindowProc(Handle, Msg, wParam, lParam); end; end; end;
Og det den gør: hvis ikke det er en message som objektet skal håndtere, kaldes standard-handleren. Dette bør man altid gøre, med mindre man har en MEGET god grund til ikke at gøre det.
Når du så vil kalde den asynkrone metode bruger du så:
her er ConnControl.Handle så en henvisning til det HWND vi definerede i interfacet og skabte i constructoren. WM_AUTODISCONNECT er typen af message, og de sidste to parametre er valgfrie integer værdier. Her er det en objektreference til et objekt jeg *VED* ikke går ud af scope.
Håber det hjalp. Og hvis du har lyst kan du såmædt sagtens se hele sourcen, men det er lidt af et monster af et program, sådan lige at sætte sig ind i :) (stofanet trafik/tids måling for flere brugere samt autosignon...) Det er GPL, så sourcen er frit tilgængeligt.
Prøv at læse det igen, langsommere. Det er lidt tungt første gang, så det skal ikke kun skimmes. Spørg hvis der er noget der er uklart formuleret. Så skal jeg nok træde til.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.