Autor Téma: ITextDocument TOM ako Thread, ktorý by dovolil okamžité prerušenie cyklu  (Přečteno 187 krát)

Online mibainfo

  • Nováček
  • *
  • Příspěvků: 16
  • Karma: 2
    • Verze Delphi: D1,2,3,4,7,2005,2009,XE8,S,B, Tokyo
Excellent
Rated 1 time
Dobrý deň, ide o spracovanie textu TRichEdit pomocou TOM (text objekt model).
Program obsahuje cykly, ktoré by bolo treba okamžite ZVONKU prerušiť v prípade potreby.
Tam kde sú v kóde otázniky by som potreboval odchod. Ale riadený ZVONKA. Cyklov je v skutočnosti omnoho viac, ako uvádzam tu.
Snáď to zabaliť ako thread a ten thread by sa mal dať prerušiť/zastaviť/killnúť.
Využíva sa COM proces (tom_tlb.pas je priložený v projekte)
Thready a COM spôsobujú nejaké špeciálne dôsledky?
Prikladám plne funkčný projekt. Je maximálne jednoduchý.
Obrázok v prílohe ukazuje program v činnosti
Vopred ďakujem za prípadnú pomoc - náčrt riešenia

Kód
Kód: Delphi [Vybrat]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   s: String;
  4. begin
  5.   if rx = nil then
  6.     rX                  := pDoc.Range( 0, 0 ).Duplicate;
  7.   for s in Zoznam do                               // pre všetky slová zo zoznamu
  8.     begin
  9.                                                    // MOŽNOSŤ prerušenia ???
  10.     while rX.FindText( s, tomForward, 0 ) > 0 do   // vyznač všetky výskyty v dokumente
  11.       begin
  12.                                                    // MOŽNOSŤ prerušenia ???
  13.       rX.Font.BackColor := rgb( 255, 200, 200 );   // podklad - staroružová farba
  14.       end;
  15.     rx.SetRange( 0, 0 );
  16.     end;
  17. end;

Poznámky:
Delphi Tokyo, kod by mal ist od XE. Iba kvoli zoznamu, inak aj v D7
EditBox v projekte nemá význam, lebo text sa vyhľadáva zo zoznamu.
« Poslední změna: 13-11-2017, 12:12:13 od mibainfo »

Online Delfin

  • Hrdina
  • ****
  • Příspěvků: 368
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Pokud vlakno (nezapomen inicializovat COM), pak urcite zmraz pred zpracovanim dokument (Freeze, Unfreeze parem). A vlakno neni treba nicit. Muzes ho vytvorit napr. pri startu aplikace s tim ze bude jen spat s cekanim na udalost.

P.S. pridej si jeste okolo zpracovani par pDoc.Undo(Integer(tomSuspend)), pDoc.Undo(Integer(tomResume)). Tim "uspis" undo buffer (uzivatel nebude moct pomoci CTRL+Z odstranit Tebou pridane zvyrazneni).
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Online mibainfo

  • Nováček
  • *
  • Příspěvků: 16
  • Karma: 2
    • Verze Delphi: D1,2,3,4,7,2005,2009,XE8,S,B, Tokyo
Ďakujem.
"Vnútrajšok" iTextDocument a jeho features poznám.
Skôr by som potreboval pomôcť s tou inicializáciou COM, ako píšeš.
Ako ju začať a ako ukončiť. Teda naviac oproti môjmu kódu.
S tým nemám moc skúsenosti. Prípadne link, kde by som to naštudoval. Vlákno + COM

Online Delfin

  • Hrdina
  • ****
  • Příspěvků: 368
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Skôr by som potreboval pomôcť s tou inicializáciou COM, ako píšeš.
Ako ju začať a ako ukončiť.

Metodu kontextu vlakna muzes obalit blokem jako je tento:

Kód: Delphi [Vybrat]
  1. procedure TMyThread.Execute;
  2. begin
  3.   CoInitialize(nil);
  4.   try
  5.     // kod kontextu vlakna
  6.   finally
  7.     CoUninitialize;
  8.   end;
  9. end;

Urcite ale nezapomen ten dokument zmrazit. Mel bys tim zamezit jak refreshi zobrazeni komponenty, tak jeji pripadne editaci. To by snad mohlo pro pristup z pracovniho vlakna stacit. Porad je to ale hra s ohnem (chovani TOM za pouziti vlaken totiz neni nikterak popsane), ktere bych se osobne vyvaroval ::)
« Poslední změna: 14-11-2017, 01:05:37 od Delfin »
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Online mibainfo

  • Nováček
  • *
  • Příspěvků: 16
  • Karma: 2
    • Verze Delphi: D1,2,3,4,7,2005,2009,XE8,S,B, Tokyo
Ďakujem, ak použijem kód z príspevku, môžem ten MyThread rozumne killnúť?
Pretože kód vlákna sa stále snaží bežať, čím premenné ITextRange a ITextDocument sú nil.
To ak platí, že ich v rámci Destroy vynulujem.
Posielam náznak konštrukcie, nie všetko. Kód, čo mám u seba je funkčný.
Ide o dve vlákna. Druhé pri štarte ruší prvé a naopak.
To je cieľ. Každé vlákno bez prerušenia trvá asi 1,3 sekundy. ( po 200 slov na 50 kB dokumente, tj 200x cyklus rx.FindText ).
Funguje to dobre, len pred každý výskyt s rx (ITextRange), musím dať kontrolu na nil, pretože thread sa z Destroy neskončí okamžite. V cykloch používam Application.ProcessMessages. Inak  sa vlákno nezruší a vždy plne dobehne.
Freeze nie je zatiaľ nutné. Ale ak by bolo treba viem, ho správne používať. V svojom hlavnom kóde ho mám husto.
Pri použití Freeze, sa ťažko preruší cyklus. Presnejšie nedá sa prerušiť.
Mohol by som poslať aj celý kód.

Kód: Delphi [Vybrat]
  1.   TMyThread = class(TThread)
  2.   private
  3.     FTerminateEvent: TEvent;
  4.   protected
  5.     pDocx : ITextDocument;
  6.     rxx   : ITextRange;
  7.     procedure Execute; override;
  8.     procedure TerminatedSet; override;
  9.     procedure FillRichEditX( zozn: TArray<String> );
  10.   public
  11.     iCase: Integer;
  12.     constructor Create(ACreateSuspended: Boolean);
  13.     destructor Destroy; override;
  14.   end;


Online Delfin

  • Hrdina
  • ****
  • Příspěvků: 368
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Ďakujem, ak použijem kód z príspevku, môžem ten MyThread rozumne killnúť?

Jak jsem uz zminoval, ten thread nech nazivu, jen ho uspi cekanim na systemove udalosti. Preruseni probihajiciho zpracovani se da zaridit jednoduse nastavenim boolean flagu. V pseudokodu:

Kód: Delphi [Vybrat]
  1. type
  2.   TMyThread = class(TThread)
  3.   private
  4.     FInterrupted: Boolean;
  5.     FTextDocument: ITextDocument;
  6.     ...
  7.   public
  8.     property Interrupted: Boolean read FInterrupted;
  9.   end;
  10.  
  11. procedure TMyThread.Execute;
  12. begin
  13.   CoInitialize(nil);
  14.   try
  15.     while not Terminated do
  16.     begin
  17.       case WaitForEventsHereForever of
  18.         EventWork:
  19.         begin
  20.           ResetEventPending;
  21.           try
  22.             FInterrupted := False;
  23.             while not Terminated and not Interrupted do
  24.               DoTheWork;
  25.           finally
  26.             SetEventPending;
  27.           end;
  28.         end;
  29.         EventExit: Exit;
  30.       end;
  31.     end;
  32.   finally
  33.     CoUninitialize;
  34.   end;
  35. end;
  36.  
  37. procedure TMyThread.DoTheWork;
  38. var
  39.   I: Integer;
  40. begin
  41.   for I := 0 to 123 do
  42.   begin
  43.     if Interrupted then
  44.       Exit;
  45.     FTextDocument.DoWhatYouNeed;
  46.   end;
  47. end;
  48.  
  49. procedure TMyThread.Process(const Document: ITextDocument);
  50. begin
  51.   Interrupt;
  52.   FTextDocument := Document;
  53.   SignalEventWork;
  54. end;
  55.  
  56. procedure TMyThread.Interrupt;
  57. begin
  58.   FInterrupted := True;
  59.   WaitForEventPending;
  60. end;

Ide o dve vlákna. Druhé pri štarte ruší prvé a naopak. To je cieľ.

Verim ze neni. Jen se budes zbytecne bit o interface jedne instance komponenty. Pokud trva nalezeni stringu v textu (volani metody FindText) radove milisekundy, bude preruseni temer stejne tak rychle. Jde o test boolean flagu ktery lze bezpecne nastavit mimo vlakno (jde o atomickou operaci).

V cykloch používam Application.ProcessMessages. Inak  sa vlákno nezruší a vždy plne dobehne.

Nikdy nevolej Application.ProcessMessages. Nikde.

Freeze nie je zatiaľ nutné.

Prave ze bude. Sahas (byt neprimo) na vizualni komponentu z pracovniho vlakna. A to je nebezpecne (ta hra s ohnem o ktere jsem psal). Pokud budes chtit, muzu poslat realnou ukazku kodu.
« Poslední změna: 14-11-2017, 15:19:40 od Delfin »
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Online mibainfo

  • Nováček
  • *
  • Příspěvků: 16
  • Karma: 2
    • Verze Delphi: D1,2,3,4,7,2005,2009,XE8,S,B, Tokyo
Ďakujem, ešte musím preštudovať tú odpoveď podrobne.
Jednu info však mám hneď teraz:
ITextRange robí v mojom veľkom vlákne len výpočty a zisťovania.
Nemení, ani nepodfarbuje text.
Inde, kde nastavujem akékoľvek Font.BackColor, Font.ForeColor, tam Freeze už volám.
Vtedy už aj tomSuspend a tomResume.
Dúfam, že toho sa prípadný problém netýka. V podstate tá engina TOM vie pracovať aj bez okna.
Tak dúfam, že pokiaľ nešahám na vizuál RichEdit, je to bezpečné.
Každopádne ďakujem.
Teraz musím niečo dokončiť a potom pošpekulujem, ako využiť tvoj pseudokód pre môj prípad.

Online Delfin

  • Hrdina
  • ****
  • Příspěvků: 368
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Ďakujem, ešte musím preštudovať tú odpoveď podrobne.

Pointy jsou v ni dve. Jedna je nenicit vlakno, ale uspat jej. Druha je prerusit bezici smycku priznakem a pockat na jeji dokonceni tak aby se dala pro dalsi zpracovani vymenit reference interface (pripadne dalsi parametry zpracovani).

Jinak moc neverim ze by byly metody ITextDocument thread safe a ze je tedy bezpecny paralelni pristup k ITextDocument referenci jedne komponenty.
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Online mibainfo

  • Nováček
  • *
  • Příspěvků: 16
  • Karma: 2
    • Verze Delphi: D1,2,3,4,7,2005,2009,XE8,S,B, Tokyo
Nemám istotu, či sú thread safe, ale dve veci sú určite zaujímavé:
1. Experimenty mi zatiaľ nespôsobili evidentný pád. To iné veci áno, ako prepísanie pamäti a pod :).
2. Trochu ma plní optimizmom, že objekty Range a Font sa získavajú ako Duplicate.
To však nie sú dôkazy. Budem informovať o prípadných skúsenostiach.
Celkom ma zaujalo toto ( obe veci sú z embarcadero návodu ):
ParallelLoop
Kód: Delphi [Vybrat]
  1. procedure TForm65.ParallelLoop;
  2. var
  3.   Tot : Integer;
  4.   SW  : TStopwatch;
  5. begin
  6.    try
  7.    // counts the prime numbers below a given value
  8.      Tot :=0;
  9.      SW  := TStopWatch.Create;
  10.      SW.Start;
  11.      TParallel.For( 2, 1, Max, procedure( I: Int64 )
  12.        begin
  13.        if IsPrime( I ) then
  14.         TInterlocked.Increment( Tot );
  15.        end );
  16.      SW.Stop;
  17.      Memo1.Lines.Add(Format( 'Parallel For loop. Time (in milliseconds): %d - Primes found: %d'#9'%d', [ SW.ElapsedMilliseconds, Tot, pocetSpusteni ] ) );
  18.    except
  19.      on E:EAggregateException do
  20.        ShowMessage( E.ToString );
  21.      end;
  22. end;

ale najmä čakanie na výsledok premennej z threadu
(vyzerá to veľmi jednoduché a aj oba kódy fungujú podľa očakávania):
IFuture
Kód: Delphi [Vybrat]
  1. ..
  2. var
  3.   Form65: TForm65;
  4.   FutureString:  IFuture<String>;
  5.  
  6. Implementation
  7. procedure TForm65.Button1Click(Sender: TObject);
  8. begin
  9.   FutureString := TTask.Future<string>(
  10.     function:string
  11.       begin      // Some calculation that takes time
  12.       Sleep( 3000 );
  13.       Result :='Hello ' + Random( 42 ).ToString;
  14.       end );
  15. end;
  16.  
  17. procedure TForm65.Button2Click(Sender: TObject);
  18. begin
  19.   Button2.Caption := FutureString.Value;
  20. end;

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Jméno: E-mail:
Ověření:
Kolik je šest plus čtyři (slovem):