Memorie scurgere atunci când lucrați cu fire

Memorie scurgere atunci când lucrați cu fire


# xA0; TMyThread = clasă (TThread)
# xA0; privat

# xA0; protejate
# xA0; # xA0; Execute procedure; suprascrie;
# xA0; public







procedura TMyThread.Execute;
începe
# xA0; FreeOnTerminate: = Adevărat;
se încheie;

procedura TForm1.Button1Click (expeditor: TObject);
începe
# xA0; TMyThread.Create (False). Terminați;
se încheie;

În acest caz, distrugătorul nu funcționează, la fel ca Execute. Am doar o situație în care, în anumite condiții, firul poate lucra timp de câteva minute, iar cu alte date de intrare fluxul poate funcționa foarte repede și Execute nu are timp să execute.
Pentru a combate scurgerea, am blocat AfterConstruction și am adăugat șirul Sleep (300) la această procedură.
Cineva a întâlnit unul similar. Cum te-ai luptat?

FreeOnTerminate: = Adevărat; este necesar să faceți înainte de a termina;


> distrugătorul nu va funcționa


> la fel ca Execute

Execute va funcționa.


> Pierderi de memorie când lucrați cu fire

Nu există nicio scurgere aici.

Ce flux? Sozdavaymy? se dovedește că execuția va fi totuși executată, timpul "fluxul se poate îndeplini"?


> pot lucra foarte repede, # xA0; și Execute nu reușește să fie executat

nu are timp să fie îndeplinită - este ca și cum? Nu ai timp să faci voluntariat? Și pentru ce scop, de fapt, este creat, dacă nu pentru împlinire # xA0; Executați?
De ce un astfel de "exemplu": # xA0; TMyThread.Create (False). Terminați;

Setați FreeOnTerminate la true dacă nu doriți să distrugeți în mod explicit firele după terminarea executării.
dar în # xA0; TMyThread.Create (False). Terminați; nu vă deranjează să o faceți în mod explicit.

Scurgerea este ceea ce? În care a ucis, fără să aibă timp să execute executarea?

În general, am întotdeauna impresia că firul Execute începe să funcționeze chiar înainte de finalizarea finalizării constructorului obiect Delphi, dacă TMyThread.Create (False)

Nu neapărat, dar este posibil. Totul depinde de modul în care planificatorul de fire de sistem distribuie sloturile de timp între firul care a numit constructorul și firul creat în acest constructor.

Închideți setarea proprietății Terminate a firului la True.







Da, și Termină # xA0; aceasta nu este distrugerea firului, ci caseta de selectare, care trebuie prelucrată în Executare. astfel încât de la Execute să nu puteți scăpa.

Verificați codul cel puțin.

Da ce să verific?

Nu există scurgeri acolo și nu pot fi, iar distrugătorul cu Execute funcționează bine, deoarece nu există premise pentru acest lucru.

Ai testat codul [0]? Nu? Dar am testat. Cu ajutorul FastMM4. Acest om nu va minți.

Uh-huh. Și acest "manager" ți-a spus direct, spun ei, metodele de Destroy și Execute nu sunt chemați, deci dacă. Sau este izolat, bazat pe speculații, și nu pe fapte?

> Sau este izolat, bazat pe speculații, și nu pe fapte
>?

Această "excludere" se bazează pe fapte. Verificați-vă în cele din urmă.


destructor TMyThread.Destroy;
începe
# xA0; moștenit;
# xA0; Windows.Beep (500, 100);
se încheie;

Cu privire la ce fapte ceva. Mai exact?


> Dacă auziți un sunet

Ce fel de grădiniță cu "sunete"?

Ați auzit despre depanatorul construit în Delphi # xA0;?

funcția ThreadProc (Thread: TThread): Integer;
var
# xA0; FreeThread: Boolean;
începe

# xA0; dacă Thread.FSuspended apoi sem_wait (Thread.FCreateSuspendedSem);

# xA0; încercați
# xA0; # xA0; dacă nu este Thread.Terminated then
# xA0; # xA0; încercați

deoarece Thread-ul deja când Terminat, atunci Execute, desigur, nu este executat

# xA0; # xA0; # xA0; Thread.Execute;
# xA0; # xA0; cu excepția
# xA0; # xA0; # xA0; Thread.FFatalException: = AcquireExceptionObject;
# xA0; # xA0; sfârșitul;
# xA0; în cele din urmă
# xA0; # xA0; FreeThread: = Thread.FreeOnTerminate;
# xA0; # xA0; Rezultat: = Thread.FReturnValue;
# xA0; # xA0; Thread.DoTerminate;
# xA0; # xA0; Thread.Finished: = Adevărat;
# xA0; # xA0; SignalSyncEvent;
# xA0; # xA0; dacă FreeThread apoi Thread.Free;

# xA0; din moment ce FreeOnTerminate = false (nu a fost apelat ECesute), atunci # xA0;
# xA0; Thread.Free nu este apelat


# xA0; # xA0; EndThread (Rezultat);


# xA0; #xA0; // Apel direct pthread_exit deoarece EndThread va desprinde firul care provoacă
# xA0; # xA0; // pthread_join în TThread.WaitFor să eșueze. # xA0; De asemenea, asigurați-vă că EndThreadProc
# xA0; # xA0; // se numește exact așa cum ar face EndThread. EndThreadProc nu ar trebui să se întoarcă
# xA0; # xA0; // și apelați pthread_exit în sine.
# xA0; # xA0; dacă este atribuită (EndThreadProc) atunci
# xA0; # xA0; # xA0; EndThreadProc (Rezultat);
# xA0; # xA0; pthread_exit (Pointer (Rezultat));

# xA0; sfârșitul;
se încheie;

Dar m-am dus și un set de designer de chemarea fir cea mai mică prioritate - și, în cazul în care linia nu Thread.Terminated condiție, atunci nu ar putea fi cu ușurință Thread.Terminated adevărat.

> Sau setați-l la Avertură înainte de Terminare.

Puteți și această opțiune. Mă voi întoarce acasă și voi lua oliță.

Ai testat codul [0]? Nu? Dar am testat. Cu ajutorul FastMM4. Acest om nu va minți.

Și fără FastMM4, puteți vedea că, cu fiecare apăsare a butonului 1, un descriptor este "mâncat".

Ați auzit despre depanatorul construit în Delphi # xA0;?
Sub instrumentul de depanare (D7), am trecut prin codul [18] și am găsit cauza scurgerii - în gătitul greșit al pisicilor.

Da. Recunosc greseala mea: (
Pur și simplu avem toate liniile de pe ferma colectivă FreeOnTerminate: = Adevărat; în Execute, așa că am crezut că a avut dreptate. Dar nu. Bummer!







Articole similare

Trimiteți-le prietenilor: