Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Libor.Karkoš 10. 06. 2018, 20:37:13
-
Dobrý den.Můj první pokus v lazaru.
Jsem si myslel, že když opráším staré učebnice ze školy, tak to dam, ale omyl :(
Toto funguje v delphi
Function OtevriThread(Param: Pointer): Longint;
begin
beep;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
thh: THandle;
thid: Cardinal;
begin
thh:=BeginThread(nil,0,@OtevriThread,nil,0,thid);
if (thh<>0) then CloseHandle(thh);
end;
V lazarusu není funkce CloseHandle, tak jsem nahradil za CloseThread(thh) a pod win take ok.
Když to však chci pod linuxem, tak mi to CloseHandle shodí celou apku.
Neporadí někdo?
-
Očividně to je špatný způsob. Tak jsem zkusil kouknout na help.
V helpu k BeginThread https://www.freepascal.org/docs-html/rtl/system/beginthread.html (https://www.freepascal.org/docs-html/rtl/system/beginthread.html) je uvedena funkce EndThread (tak jako to bývá u typicky párových funkcí ve všech dokumentacích všech jazyků, u otevírací je zmíněno jak se naopak zavírá) která zavře současné vlákno https://www.freepascal.org/docs-html/rtl/system/endthread.html (https://www.freepascal.org/docs-html/rtl/system/endthread.html).
Proč by někdo chtěl zavírat současné vlákno a ne nějaké jiné? Protože zavraždit nějaké jiné vlákno je špatné, samo vlákno se má rozhodnout že chce skončit protože ví v jakém je stavu a že je to bezpečné. Co kdyby třeba to vlákno mělo otevřený handle souboru? Naalokovanou paměť? Typicky v jiných programovacích jazycích se to řeší tak že "worker" má cyklus ve kterém vykonává práci (a třeba čas od času zavolá nějakou funkci kterou dá najevo že toho udělalo dost a že mohou třeba začít pracovat jiná vlákna (docela užitečné na jednovláknovém systému)), a jen si čas od času kontroluje jestli nemá skončit.
Ve to zdá se funguje podobně - něco je popsáno v http://wiki.freepascal.org/Multithreaded_Application_Tutorial (http://wiki.freepascal.org/Multithreaded_Application_Tutorial) a používá se funkce Terminate. Ale trochu jednodušeji mi přijde že je to vysvětleno v https://stackoverflow.com/questions/3788743/correct-thread-destroy (https://stackoverflow.com/questions/3788743/correct-thread-destroy) či https://stackoverflow.com/questions/3557105/free-a-tthread-either-automatically-or-manually?noredirect=1&lq=1 (https://stackoverflow.com/questions/3557105/free-a-tthread-either-automatically-or-manually?noredirect=1&lq=1) případně https://stackoverflow.com/questions/4044855/how-to-kill-a-thread-in-delphi (https://stackoverflow.com/questions/4044855/how-to-kill-a-thread-in-delphi).
Osobně mi ale přijde že nějak Free Pascalu chybí nějaký jednoduchý a rychlý tutorial na tohle :-(.
-
Nezávisle na platformě by měla fungovat třída TThread:
https://www.freepascal.org/docs-html/rtl/classes/tthread.html
Zdědit a napsat vlastní funkci Execute.
Jednoduchý příklad viz. dokumentace:
/examples/multithreading/
-
Tak mi to nedalo a hledal jsem jak to pořešít.
http://forum.lazarus.freepascal.org/index.php?topic=11011.0
Tu klučina píše, že místo CloseHandle použil EndThread.
var
Form1: TForm1;
thh: THandle;
implementation
{$R *.lfm}
{ TForm1 }
Function OtevriThread(Param: Pointer): Longint;
begin
beep;
EndThread (thh);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
thid: Cardinal;
begin
thh:=BeginThread(nil,0,@OtevriThread,nil,0,thid);
end;
Při kliknutí na gombik se vytvoří vlákno, které provede to co chcí a pak se samo ukončí.
Je to funkční a vypadá že i v pořádku ;)
-
Ale ne pod linuxem :'(
Zasek mi to shodí celou apku
-
Dalo by se poslat kompletní kód který aktuálně používáš a ktery tedy nefunguje? Jestli tam máš více logiky (kterou třeba nechceš zveřejnit) tak to zjednoduš až na minimální příklad který stále crashuje.
Psal na to třeba můžeme zkusit mrknout, nebo zkusit zreplikovat.
-
Ale ne pod linuxem :'(
Zasek mi to shodí celou apku
V Linuxu musí být pro vícevláknovou aplikaci v projektu unity navíc:
http://wiki.freepascal.org/Multithreaded_Application_Tutorial#Units_needed_for_a_multi-threaded_application
jestli třeba není problém v tom.
-
Dalo by se poslat kompletní kód který aktuálně používáš
Není žádný kompletní kod.
Teprve chci můj projekt předelat do vlakna, tak zkouím zda to pujde.
Prostě jeden button a jedna funkce.
-
Dalo by se poslat kompletní kód který aktuálně používáš
Není žádný kompletní kod.
Teprve chci můj projekt předelat do vlakna, tak zkouím zda to pujde.
Prostě jeden button a jedna funkce.
>>> Multiplatformní zapouzdření třídou TThread
-
Tak problémy s chybovými hlášky při spouštění a i to padaní apky řeší toto.
http://forum.lazarus.freepascal.org/index.php?topic=18470.0
Problém je, že se mi žadné vlákno nespustí.
http://delphiexamples.com/application/appsynchthread.html
-
Klucí, ještě by byl jeden dotaz.
Jak správně zapisovat z vlakna třeba do labelu
procedure TTestThread.Execute;
var
s: string;
begin
s:=StavExpanderu('i2cget -y 1 0x22 0x13');
Form1.Label1.Caption:= s;
Form1.Memo1.Clear;
Form1.Memo1.Lines.Add(s) ;
end;
Memo je ok.
Label vyhazuje http://img24.cz/images/86959613333661778055.png
Když to upravím takto tak stejný problém
Form1.Label1.Caption:= '';
Form1.Label1.Caption:= s;
Když to však mam takto, tak to funguje.Proč?
Form1.Label1.Caption:= 'xxx';
Form1.Label1.Caption:= s;
Co dělam špatně?
-
Klucí, ještě by byl jeden dotaz.
Jak správně zapisovat z vlakna třeba do labelu
procedure TTestThread.Execute;
var
s: string;
begin
s:=StavExpanderu('i2cget -y 1 0x22 0x13');
Form1.Label1.Caption:= s;
Form1.Memo1.Clear;
Form1.Memo1.Lines.Add(s) ;
end;
Memo je ok.
Label vyhazuje http://img24.cz/images/86959613333661778055.png
Když to upravím takto tak stejný problém
Form1.Label1.Caption:= '';
Form1.Label1.Caption:= s;
Když to však mam takto, tak to funguje.Proč?
Form1.Label1.Caption:= 'xxx';
Form1.Label1.Caption:= s;
Co dělam špatně?
Dělá se to pomocí Synchronize a popsáno je to na wiki:
http://wiki.freepascal.org/Multithreaded_Application_Tutorial#The_TThread_Class
odkazy posílal výše sj měl by sis to přečíst, ušetří ti to čas a docela objasní spoustu věcí souvisejících s vlákny...