Autor Téma: DB Query ve vlakne a vykresleni vysledku na tFlowLayout  (Přečteno 4836 krát)

Offline raul

  • Hrdina
  • ****
  • Příspěvků: 468
  • Karma: 15
    • Verze Delphi: FPC :D
Zdar,
nejak jsme se debilne zasek na asynchronnim dotazem do db (postgresDac) a naslednym vykreslenim vyslekdu do flowlayout.
Na formu mam Edit a v eventu OnChangeTracking spoustim dva dotazy do db. Prvni vyhleda slova podobna zadanemu, pro kazde vytvori label (idealne pak v rectangle) a mrskne ho na flowlayout. Nejak ovsem zapasim s tTask.Run vlakny, synchronizaci apod (seznam labelu se vzdy pred dotazem komplet maze (vyslekdy se dost lisi i s pismenem, tudiz neni duvod to nejak cachovat). Dotaz do db trva nekdy par vterin,  proto ho nechci poustet primo v hlavnim vlakne. Na druhou stranu, kdyz napisu dalsi pismeno, bylo by prima ten task ukoncit (ve while muzu mit podminku).

Druhy dotaz do db je +- podobny, na druhy tlayout se doplni panel se 2 labely a jednim obrazkem (ten se dotahuje pres synapsi z https). Toto by take slo udelat jako spesl tasky (pak je ale otazka, jak nalozit s jiz zmizelymi timage (protoze uzivatel pise dale a tudiz jiz data nejsou platna)). Cele to ma byt jednoducha utilitka, takze jsem si chtel ujednodusit praci, nez vytvaret sve vlakna, frontu pozadavku apod).

Je mozne nejakej nakopnuti ?

UpdateWords:

smaz obsah

task.run
(
  criticalsection.acq;
  pust dotaz do db
  tthread.synchronize
 (
   words.beginupdate;
   try
   while not eof do
   .
   .
   .
   finally
     words.endupdate;
   end;
 )
 criticalsection.leave;
)

Jako ono to +- funguje, akorat ze i pres begin/end update se obcas proste labely prekreslujou pres sebe a pomuze jen resize okna formulare.

P.S.> GUI aplikace skorem nedelam, max obcas nejakou takovouhle utilitku, tak s tim zapasim..
« Poslední změna: 07-11-2020, 20:12:17 od raul »
Lazarus 1.6.3:), FPC, Intel/Arm, Windows/Linux, (občas Delphi)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3534
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:DB Query ve vlakne a vykresleni vysledku na tFlowLayout
« Odpověď #1 kdy: 08-11-2020, 06:59:08 »
Jako ono to +- funguje, akorat ze i pres begin/end update se obcas proste labely prekreslujou pres sebe a pomuze jen resize okna formulare.
S opici nedelam, ale ve VCL bylo obvykle, ze Begin/End update jen zamezovalo propagovani zmeny dat dal tj. prekreslovani, generovani udalosti apod., ale netykalo se exkluzivniho pristupu.

Resil bych to tak, ze v okamziku, kdy BFU zmeni hledany pattern, tak bych existujici tasky nejak "odstrihl" od UI a bud je nechal na pozadi dobehnout bez vlivu na UI nebo je nejak ukoncil tj. zajistil, ze v jeden okamziku mam jen jednu sadu dotazu, jejichz vysledek poleze do UI a ktery bude odpovidat posledni zmene provede BFU.

Offline raul

  • Hrdina
  • ****
  • Příspěvků: 468
  • Karma: 15
    • Verze Delphi: FPC :D
Re:DB Query ve vlakne a vykresleni vysledku na tFlowLayout
« Odpověď #2 kdy: 08-11-2020, 13:53:37 »
Diky, me slo prave o praci s taskem (tzn jak rozumne ukoncovat apod), a parametry pro prenos mezi synchronize a prave v FMX. Zkousel jsem to napsat ve VCL a tam to chodilo o dost rychleji a o dost lepe (kod komplet zkopirovan a jen upraven pro kompatibilitu s vcl.

Viditelne je cely fmx napsany stejne kvalitne jako dalsi casti kodu - pomale, s x novymi - ne vzdy zdokumentovanymi postupy/vlastnostmi.
Lazarus 1.6.3:), FPC, Intel/Arm, Windows/Linux, (občas Delphi)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3534
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:DB Query ve vlakne a vykresleni vysledku na tFlowLayout
« Odpověď #3 kdy: 08-11-2020, 15:59:36 »
Diky, me slo prave o praci s taskem (tzn jak rozumne ukoncovat apod), a parametry pro prenos mezi synchronize a prave v FMX. Zkousel jsem to napsat ve VCL a tam to chodilo o dost rychleji a o dost lepe (kod komplet zkopirovan a jen upraven pro kompatibilitu s vcl.
Ani s tasky jsem v Delphi nic podstatnejsiho nedelal, v C# ma konstruktor parametr CancelationToken, ktery jsem mu predaval a kterym lze tasku signalizovat, ze to ma zabalit. Jestli ma neco podobneho TTask nevim.

Jinak by melo stacit mu pred startem tasku vygenerovat a predat nejake sekvencni cislo, ktery by na zacatku metody v Synchronize porovnal a kdyz by mu nesouhlasilo, tak by nic nedelal. Pak by stacilo jen pri kazde zmene to cislo inkrementovat. Vlastni exkluzivitu by mu zajistilo to Synchronize, protoze ve VCL  je implementovano zaslanim zpravy WM_NULL do hlavniho threadu (GUI), pokud se v nem nestoura do pumpy zprav napr. volanim Application.ProcessMessages.

Ale jak je to v opici pripadne na jinych platformach nevim.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3534
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:DB Query ve vlakne a vykresleni vysledku na tFlowLayout
« Odpověď #4 kdy: 08-11-2020, 16:06:37 »
[...]
v C# ma konstruktor parametr CancelationToken, ktery jsem mu predaval a kterym lze tasku signalizovat, ze to ma zabalit. Jestli ma neco podobneho TTask nevim.
Podle Helpu bych to v Delphi zrejme delal pres ITask, ktere ma metody Cancel a CheckCanceled

Offline raul

  • Hrdina
  • ****
  • Příspěvků: 468
  • Karma: 15
    • Verze Delphi: FPC :D
Re:DB Query ve vlakne a vykresleni vysledku na tFlowLayout
« Odpověď #5 kdy: 08-11-2020, 16:43:35 »
To s tim cislem neni spatnej napad. Zatim to prave delam pres iTask a ted mi doslo, ze sice ja ho cancelnu, ale EndUpdate prekresli ty data, co do te doby zmenim. Matlo me, ze ten cancel mi nefunguje jak ma, ale ono to asi bude timhle. Protoze kdyz napisu rychle nejakej text, tak celkove vykresleni je treba za 2s. Pritom jeden dotaz trva 30ms.. Zkusim se podivat jestli neni neco jako nasilnej CancelUpdate u toho FlowLayoutu
Lazarus 1.6.3:), FPC, Intel/Arm, Windows/Linux, (občas Delphi)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3534
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:DB Query ve vlakne a vykresleni vysledku na tFlowLayout
« Odpověď #6 kdy: 08-11-2020, 17:28:17 »
ze sice ja ho cancelnu, ale EndUpdate prekresli ty data, co
Cancel jen nastavi priznak, ze se na to ma vybodnout, takze ty bys ho mel testnout nejpozdeji pred BeginUpdate a to by ti melo poslouzit misto toho sekvencniho cisla - u toho reseni spis jde o to, co pro tebe bude snazsi, jestli distribuovat do vsech tasku jedno cislo nebo si pamatovat iTask pro vsechny rozebehnute tasky. Ale princip je stejny: nevstupovat do UI operaci nebo nechat na Synchronize, ze ti zajistit serializaci aktualizaci UI z jednotlivych tasku. Jakmile se ta aktualizace rozebehne, uz to bude delat vizualni "bordel"
« Poslední změna: 08-11-2020, 17:32:52 od pf1957 »

Offline raul

  • Hrdina
  • ****
  • Příspěvků: 468
  • Karma: 15
    • Verze Delphi: FPC :D
Re:DB Query ve vlakne a vykresleni vysledku na tFlowLayout
« Odpověď #7 kdy: 08-11-2020, 18:48:19 »
JJ tomu zhruba rozumim.
de facto takto :
SQL.OPEN;
synchronize
(
   flow.beginuprade;
   WHILE not sql.eof
   (
      // create polozky
     try
        checkcanceled
     except
        break;
     end;
     SQL.Next;
   )
   flow.endupdate; // ten se provede pro jiz vytvorene polozky i kdyz se jedna o cancel, a de facto to uz vykreslovat ani nemusi.
)

Mohu begin/end update mrsknout mezi kazodu polozku, ale to mi prislo priliz nasilne. K prekresleni aktualne vytvorenych by doslo stejne, byt mozna pro uzivatele prijemneji - i z pohleud, ze kdyz je polozek 20++ tak to vykresleni samozrejme trva a ui trochu laguje. Jinak tyhle tasky mam dva (pak samozrejme par dalsich, s temi obrazky apod, ale ty uz nijak neresim, tam se - i jak si psal - proste nactou nebo uvolnej z pameti - po stazeni).
Lazarus 1.6.3:), FPC, Intel/Arm, Windows/Linux, (občas Delphi)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3534
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:DB Query ve vlakne a vykresleni vysledku na tFlowLayout
« Odpověď #8 kdy: 08-11-2020, 21:51:19 »
Ja bych to udelal nejak takto:
Kód: Delphi [Vybrat]
  1. SQL.OPEN;
  2. synchronize
  3. (
  4.    if task.Status in [TTaskStatus.Canceled,...] then
  5.     exit;
  6.    flow.beginuprade;
  7.    WHILE not sql.eof
  8.    (
  9.      ...
  10.      SQL.Next;
  11.    )
  12.    flow.endupdate; // ten se provede pro jiz vytvorene polozky i kdyz se jedna o cancel, a de facto to uz vykreslovat ani nemusi.
  13. )
  14.  
Pripadne jeste test uvnitr while...

Offline raul

  • Hrdina
  • ****
  • Příspěvků: 468
  • Karma: 15
    • Verze Delphi: FPC :D
Re:DB Query ve vlakne a vykresleni vysledku na tFlowLayout
« Odpověď #9 kdy: 08-11-2020, 21:53:26 »
Tvl, vlastne jo. Uz mi hrabe, veci k reseni qvadrilion, asi bych potreboval dovcu..

Ja ho mam az uvnitr toho cyclu pres SQL. Pridam jeste sem.

Diky moc.
Lazarus 1.6.3:), FPC, Intel/Arm, Windows/Linux, (občas Delphi)