02. marts 2008 - 22:53Der er
6 kommentarer og 1 løsning
Hvordan undgår jag at mit program går i 'svarer ikke'?
Jeg har en rutine den gennemsøger alle poster i en database, (Fritekst søgning). Databasen har cirka 150.000 records og de fleste af gangene går programmet i 'svarer ikke mode'. Programmet søger dog videre, og når alle records er gennemløbet vises resultatet og programmet svarer igen. Hvordag undgår man at programmet går i 'svarer ikke'? Jeg har forsøgt med tråde, men det blev søgningen da umanerlig langsom af.
procedure TForm36.Find; begin List.Clear; begin Global.TTitel.IndexName := ''; with Global.Titel.DataSet do begin Refresh; First; while not (EOF) do begin Led; Next; end; end; end; end;
procedure TForm36.Led; begin with Global.Titel.DataSet do begin Refresh; if (FieldByName('Plade').AsInteger <> 0) and FieldByName('Aktiv').AsBoolean then begin if (not SkalVaerePaaPc) or (FieldByName('PåHdd').AsBoolean) then begin if Pos(AnsiUpperCase(Titel.Text), AnsiUpperCase(FieldByName('Titel').AsString)) > 0 then Ind; if Pos(AnsiUpperCase(Titel.Text), AnsiUpperCase(FieldByName('Alternativ').AsString)) > 0 then Ind; if Pos(AnsiUpperCase(Titel.Text), AnsiUpperCase(FieldByName('Original').AsString)) > 0 then Ind; end; end; end; end;
procedure TForm36.Ind; begin Global.Plade.DataSet.Refresh; Global.TPlade.IndexName := ''; Global.TPlade.FindNearest( [IntToStr(Global.Titel.DataSet.FieldByName('Plade').AsInteger)]); Tmp := Global.Using(Global.Plade.DataSet.FieldByName('Nummer').AsInteger); while Length(Tmp) < 10 do Tmp := ' ' + Tmp; Tmp := Tmp + Global.Titel.DataSet.FieldByName('Titel').AsString + ' '; while Length(Tmp) < 46 do Tmp := Tmp + ' '; Tmp := Tmp + Global.Titel.DataSet.FieldByName('Kunstner').AsString + ' '; while Length(Tmp) < 82 do Tmp := Tmp + ' '; Tmp := Tmp + Global.Plade.DataSet.FieldByName('Medie').AsString + ' '; if Global.Titel.DataSet.FieldByName('PåHdd').AsBoolean then Tmp[86] := '*'; Tmp := Tmp + IntToStr(Global.Titel.DataSet.FieldByName('Index').AsInteger); List.Items.Add(Tmp); Fundne.Clear; Fundne.Items.Add(IntToStr(List.Items.Count)); Form36.Update; // Denne linie var et forsøg på om det kunne afhjælpe fejlen. end;
Routinen 'Find' gennemløber databasen en record ad gangen. Det er routinen 'Find' der tager for lang tid. Routinen 'Led' laver fritekst søgning på tre poster i den aktueller record, og hvis et match er fundet kaldes routinen 'Ind', til at formatere linien til ListBoksen.
Jeg tror nedenstående vil fikse det. Hvis du gerne vil have skærmen opdateret lidt mere kan du sætte antallet af processMessages op ved at sætte 100 ned til eksempelvis 50.
procedure TForm36.Find; var i: integer; begin i := 0; List.Clear; begin Global.TTitel.IndexName := ''; with Global.Titel.DataSet do begin Refresh; First; while not (EOF) do begin i := i + 1; if (i mod 100) = 0 then Application.ProcessMessages; Led; Next; end; end; end; end;
i := i + 1; if (i mod 100) = 0 then // For hvert 100 gennemløb Application.ProcessMessages;
... burde flyttes under Led
Et alternativ til at tælle records er at lave timeouts:
procedure TForm36.Find; var TickStart: cardinal; begin List.Clear; begin Global.TTitel.IndexName := ''; with Global.Titel.DataSet do begin Refresh; First; TickStart := GetTickCount; while not EOF do begin Led; if (GetTickCount - TickStart) >= 1000 then // For hvert sekund begin Application.ProcessMessages; TickStart := GetTickCount; end; Next; end; end; end; end;
Endelig kan du måske, men her er det vist en dum idé, bruge Application.HandleMessage.
Jeg kaldte Application.ProcessMessages; hver gang et hit blev fyldt i Listbox. Jeg ved godt at den ikke er konsekvent, det er mulig at jeg laver det om lidt senere. Jeg hælder mest til den der trigger en gang i sekundet.
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.