Ó théama an iris go cleachtas tionscadail
Leathanaigh seirbhíse agus teicniúla oiriúnacha don alt
Má tá tú i Delphi ag iarraidh tascanna dian ríomhchumhachta nó tascanna atá trom le I/O a rith go comhthreomhar, téann tú go tapa chuig an Parallel Programming Library (PPL) agus go sonrach chuig TParallel.For. Is minic a bhíonn an tionchar le feiceáil láithreach — go dtí go dteastaíonn uait, sa nóiméad céanna, an Progress-UI a nuashonrú “go tapa”. Sa chás sin cruthaítear na hadhnáin tipiciúla: reoanna UI a thagann de thaisme, ProgressBar a léimeann siar, nó deadlock iomlán nuair a théann tú tríd an Debugger céim ar chéim.
Sa trácht seo tá sé faoi TParallel.For Progress-UI atá sábháilte ó thaobh snáitheanna: patrún seasta a oibríonn i VCL agus FMX, a chomhcheanglaíonn nuashonruithe UI go glan trí TThread.Queue, a chuireann Cancel/Abort san áireamh agus a sheachnaíonn go córasach na greamaithe deadlock is coitianta. Tá an fócas ar réaltacht oibríochta: iompraíocht inathnuaite, freagrachtaí soiléire agus leideanna dífhabhtaithe a chabhraíonn fiú nuair a tharlaíonn an locht ach amháin “bei Kunden”.
Cén fáth a mbíonn Progress-UI le TParallel.For chomh minic mícheart
TParallel.For rithtear de ghnáth ar worker-threads ón Delphi-Threadpool. Ní cheadaítear do na snáitheanna sin rialuithe VCL nó FMX a láimhseáil go díreach, mar tá na frámaí oibre UI (Message Loop, Window Handles, Rendering) ceangailte leis an Main Thread. Féadann fiú ProgressBar.Position := … a ritheann ó snáithe oibre iompraíocht neamhchinnte a ghiniúint: AVs sporadacha, fuinneoga reoite nó nuashonruithe neamhchobhsaí.
An socrú is coitianta is ea TThread.Synchronize. Cé gur réitíonn sé slándáil snáitheanna, cruthaíonn sé i lúbanna chomhthreomhara go tapa fadhb eile: bac sraitheach. Fanann gach worker ar an UI-Thread, agus bíonn an Main Thread gnóthach leis an rindreáil agus le glaonna Synchronize a phróiseáil. Faoi ualach d’fhéadfadh sé seo breathnú cosúil le deadlock — fiú má tá sé i ndáiríre ach éifeacht starvation/lockstep.
Agus ansin tá an cineál deadlock fíor: fanann an Main Thread (m.sh. trí WaitFor, Task.Wait nó go hindíreach trí ghlaonna blocálacha) ar chríoch na hoibríochta chomhthreomhara, agus iarracht a dhéanann na worker-threads post a chur chuig an Main Thread trí Synchronize nó trí úsáid míchuí de Queue. Toradh: tá an Main Thread ag fanacht ar na workers, agus tá na workers ag fanacht ar an Main Thread.
TThread.Queue vs. TThread.Synchronize: der praktische Unterschied
Fágann an dá mheicníocht cód a rith go sábháilte sa Main Thread. Is í an difríocht ná an seamnantas fanachta:
- TThread.Synchronize: Fanann an worker a ghlao go dtí go ndéanann an Main Thread an cód a fhorghníomhú. Tá sé sioncrónach, méadaíonn sé ltiantais agus is comhábhar coitianta é do deadlocks nuair atá an Main Thread blocáilte.
- TThread.Queue: Cuireann an Worker an cód i gcuntas feithimh amháin don Main Thread agus leanann sé ar aghaidh. Tá sé sin „asíncrónach“, scarann sé snáitheanna agus is é an rogha réamhshocraithe níos fearr beagnach i gcónaí i gcásanna paraléil – má bhíonn tú in ann minicíocht na nuashonruithe a rialú.
Tábhachtach: Queue ní bhfaigheann sé pas iomlán duit. Má sheolann tú nuashonrú Queue i ngach itríocht lúb, líonann tú Main-Thread-Queue. Ní bheidh an UI greamaithe de bharr deadlock ansin, ach de bharr an ualach ollmhór teachtaireachtaí. Beidh an UI «mall», agus déanfar deireadh na próiseála a mhoilliú mar gheall ar na céadta nó mílte nuashonrú UI atá fós i bpróiseáil.
An cás imeallach a gortaíonn i ndáiríre: Fanacht sa UI-Thread
I n-iarratais chorparáideacha feictear go minic an sreabhadh seo: cliceáil ar an gcnaipe „Start“, díghníomhachtaítear an UI, osclaítear an ProgressDialog, ansin fanann an clár go sínchrónach go dtí go mbeidh gach rud críochnaithe, agus ansin déantar athghníomhachtú. Is é an patrún seo croí go leor deadlocks.
Leaganacha tipiciúla (ag brath ar an mbonnchód):
- Main Thread tosaíonn TParallel.For agus glaonn sé ina dhiaidh sin ar loighic fanaithe blocála (go díreach nó go hindíreach).
- Glaonn ProgressDialog sa Constructor nó sa OnShow ar ghnáthamh a fhánann go hinmheánach.
- Bíonn cnaipe Abbrechen ag socrú bratach, ach fanann an Main Thread fós i lúb fanaithe.
Mura bhfuil Worker-Threads úsáid á baint as an Synchronize sa tréimhse seo, tá an deadlock beagnach cinnte. Is féidir go mbeadh greamú ann le Queue freisin má tá an Main Thread blocáilte agus nach bhfuil sé ag pumpáil teachtaireachtaí — toisc nach ndéanfar an Queue a phróiseáil ansin ach an oiread.
Is é an toradh oibríochta atá iontaofa: Níor chóir don Main Thread fanacht go blocálaí ar an lúb paraléil má iarrtar nuashonruithe UI go comhuaineach. Ina áit sin ní mór an phróiseáil a chur go hiomlán i dtasc cúlra, nó eagrófar „deireadh asíncrónach“ (Callback/Queued gníomh críochnaithe) a scaoilfidh an UI arís ag an deireadh.
Cur chuige glan: Progress ach amháin i mbailiú, nuashonruithe UI riainithe
Tá patrún iontaofa comhdhéanta de thrí fhreagracht shoiléir scartha:
- Worker-Threads déanann siad an obair iarbhír in aghaidh an eilimint/innéacs. Tuairiscíonn siad ach an dul chun cinn i bhfoirm shlán ó thaobh snáithí de (comhaire, Queue, Thread-safe Queue).
- Aggregator (go minic: Main Thread nó timer tiomnaithe sa UI) ríomhann sé stádas UI ón dul chun cinn (suíomh, téacs, ETA) agus nuashonraíonn sé na rialuithe. Mar sin seachnaíonn tú nuashonruithe 1:1 in aghaidh gach itríochta.
- Críochnú (arís sa Main Thread): athghníomhachtaigh an UI, taispeáin an torthaí, déan achoimre ar earráidí agus saor acmhainní.
Cén fáth a n-oibríonn an scaradh seo chomh maith: Is féidir go mbeadh an ualach oibre ardminicíocht (na mílte eilimintí), ach níl sa UI ach cúpla nuashonrú sa soicind. Sa chleachtas, bíonn 5–10 nuashonrú/s go leor; i dtascanna an-tapa fiú 2–4. Is minic go mbíonn gach rud os cionn sin ach torann amhairc agus go n-íditíonn sé am CPU sa Message Pump.
Comhaireamh sábháilte snáithe: Atomach seachas Lock
Do ProgressBar shimplí is minic go leor go leor go leor cén fáth go leor—is minic go leor—níos mó. „Atomach“ ciallaíonn: déanann Inkrement agus Read gan Coinníoll Rása, de ghnáth trí TInterlocked. Ar an gcaoi sin seachnaíonn tú Locks (Critical Sections) i mbóthar te an lúba.
Smaoineamh íosta cruthaithe:
- Tá an méid iomlán ar eolas roimh ré (m.sh. líon na dtaifead, comhadanna, IDanna).
- Innealtaíonn gach lúb an DoneCounter go atomach.
- Léann UI-Timer an counter go tréimhsiúil agus socraíonn sé ProgressBar.Position.
Buntáiste: Níl TThread.Queue do gach eilimint, níl an UI plódaithe. Míbhuntáiste: Níl teachtaireachtaí mionsonraithe agat do gach eilimint (m.sh. ainm comhaid). Ina ionad sin is féidir teachtaire stádais dara, laghdaithe a chur leis (féach an chéad chuid eile).
Teachtaireachtaí stádais gan spam: „an stádas deireanach a bhuaileann“
Má theastaíonn uait téacs gearr a thaispeáint freisin (eilimint reatha, céim, teachtaireacht earráide), teastaíonn patrún a sheachnaíonn flóid an UI ag gach céim oibre. Sa chleachtas oibríonn an patrún „an stádas deireanach a bhuaileann“ go maith:
- Scríobhann an Worker eolas stádais i struchtúr sábháilte snáithe (m.sh. String inathraithe go atomach, nó cosanta le lock beag).
- Glacann UI-Timer go tréimhsiúil leis an stádas is déanaí agus cuireann sé isteach é i Label.
Mar sin fanann an UI freagrach, agus feiceann tú fós go bhfuil „rud éigin ag tarlú“. Níor chóir tagairtí do réada gearshaolacha ó snáithíní oibre a iompú isteach sa snáithín UI. Má sheolann tú réada, socraigh úinéireacht go soiléir.
TParallel.For snáithe-sábháilte Progress-UI le TThread.Queue: patrún iontaofa
Tá cásanna ann nach leor UI-Timer amháin: mar shampla, má theastaíonn uait a bheith cinnte go gcuirfear díreach aon nuashonrú „Críochnaithe“ ag an deireadh, nó má tá an nuashonrú UI níos casta (m.sh. iontráil i bhfhuinneog log, ach laghdaithe). Ansin is oiriúnach TThread.Queue — ach ní do gach lúb, ach go beacht.
Cur chuige praiticiúil ná Queue amháin d’imeachtaí le minicíocht íseal:
- Start-Event (UI a ullmhú, cnaipí a chur faoi ghlas)
- Periodische Progress-Events (uasmhéid gach X milliseicind)
- Fehler-Events (roghnach, bailithe)
- Done-Event (UI a athshocrú, toradh a thaispeáint)
Ní bhfaightear an tréimhsíchas tríd an snáithín UI, ach cheana féin i gcomhthéacs an worker: ligfidh tú do worker UI-nuashonrú a „queue“áil ach amháin má tá am leordhóthanach imithe thart ón nuashonrú deireanach. Oiriúnach anseo ná foinse ama monotónach (m.sh. TickCount) chomh maith le luach „last update“ atomach.
Tábhachtach: caithfidh an nuashonrú UI féin a bheith „tapa“. Níor chóir ríomhanna costasacha, I/O comhad nó rochtain ar bhunachar sonraí a áireamh sa UI-callback atá gequeued. Ba chóir don callback ach staid a léamh agus rialuithe a shocrú.
Láimhseáil Cealaithe: Cealú gan crochadh
I bhfeidhmchláir réadúla, ní roghnach é cealú. Tá sé ríthábhachtach: ní „Kill“ é Cancel, ach críochú comhoibríoch. Ní mór do workers go minic a sheiceáil an bhfuil comhartha cealaithe socraithe, agus ansin imeacht go glan. I Delphi tá roinnt bealaí ann (ag brath ar thógáil PPL): ceann féin Volatile-flag, boolean atomach, nó coincheap Cancellation trí Tasks (ag brath ar leagan agus struchtúr Delphi).
Tá dhá riail thábhachtacha don oibriú:
- Caithfidh „Cealaigh“ a bheith le feiceáil go tapa: Seiceáil an Abbruchflag i suíomhanna ciallmhara, ní hamháin ag deireadh gach Iteration má d’fhéadfadh an Iteration sin roinnt soicindí a thógáil.
- Caithfidh „Cealaigh“ a ghlanadh suas: Níor cheart go bhfanfadh handles oscailte, comhaid shealadacha, idirbhearta nó locks. Ciallaíonn sé seo: i ngach Iteration de Worker tá blocanna try/finally riachtanach má tá acmhainní i gceist.
Ar thaobh an UI, ba chóir do „Cealaigh“ ach comhartha a shocrú agus an UI a chuir i staid „Stopping…“. Tá an chríochnú iarbhír agus an athghníomhachtú an UI le tarlú ansin sa Done-Event, ní láithreach tar éis an chliceáil.
Deadlocks a sheachaint: na titimí is coitianta sa chleachtas
Fadhb 1: WaitFor/Task.Wait sa Main Thread
Nuair a bhacann an Main Thread, ní féidir leis callbacks Queue a fhorghníomhú ná teachtaireachtaí a phróiseáil. Feictear é sin mar deadlock, fiú má leanann na Workers ag rith i gceart. Réiteach: ná húsáid waits bhlocálacha ar an UI-Thread. Ina ionad sin déan an gníomh críochnaithe trí TThread.Queue nó trí rialú imeachtaí (m.sh. seiceálann Timer an stádas „críochnaithe“).
Fadhb 2: Synchronize taobh istigh de Lock
Clasaiceach: coinníonn Worker Critical Section, glaonn sé ansin Synchronize, agus san UI-callback iarrtar (go díreach nó go hindíreach) an Critical Section chéanna arís. Toradh: fáinne feithimh. Tá an riail simplí: ná déan pasáil chuig an UI (Synchronize/Queue) ó laistigh de Lock atá á choinneáil. Má tá Lock riachtanach, bain na sonraí go léir isteach i n-athróga áitiúla ar dtús, fág an Lock, agus ansin déan an queue.
Fadhb 3: UI-Callback spreagann Reentrancy
Uaireanta ní ’náire‘ é an nuashonrú UI féin: d’fhéadfadh suímh Airíonna (Properties) ócáidí a ghiniúint (OnChange, OnResize) a chuireann i bhfeidhmíocht eile faoi bhrú a rochtain stáit na Workers. Ní hé seo deadlock sa bhrí dhúnta, ach cruthaíonn sé greamaithe nach bhfuil furasta a mhíniú agus coinníollacha race. Réiteach: cuir nuashonruithe UI i mbealaí ‚ciúine‘ (díchumasaigh imeachtaí go sealadach) nó bain úsáid as reentrancy-guards (m.sh. guard adamhach don chéim nuashonraithe).
Fadhb 4: Ró-mhór líon nuashonruithe queued
Fiú gan waits, féadfaidh an UI
Don UI seo chiallaíonn sé: ná taispeáin gach teachtaireacht earráide láithreach. Beireann sin ar an gcás go leor dialóg modúil. Bailigh earráidí (m.sh. liosta sreingeanna) agus taispeáin achoimre ag an deireadh nó log a easpórtáil.
Díbhristeáil: Conas an deadlock a dhéanamh i ndáiríre le feiceáil
Tá deadlocks i gcód chomhthreomhara frustrach, toisc gur féidir leo breathnú go difriúil sa debugger ná sa Release. Tá cúpla bealach praiticiúil ann áfach:
Úsáid an fhuinneog Snáitheanna agus na Stacanna Glaonna
Má tá an UI sáinnithe, féach ar na snáitheanna go léir: cá bhfuil an snáithe príomha? An bhfuil sé ag fanacht? An bhfuil sé i bhfána fáinne teachtaireachta? Cá bhfuil na snáitheanna oibre? Má tá snáitheanna oibre sáinnithe i Synchronize, is iondúil go bhfuil an chúis “snáithe príomha blocáilte” nó “teastaíonn lock ón snáithe príomha”.
Marcáil na suíomhanna Queue/Synchronize
Cuir logáil go beacht ag na pointí aistrithe (roimh an Queue, sa Queue-Callback, ag deireadh na hidirghníomhach). Sa timpeallacht tá sé seo annamhluachmhar ó thaobh níos mó ná breakpoints, toisc go bhfuil an t-amáil ríthábhachtach. Bí cinnte nach bhfuil an logáil féin ina chúis le saincheist snáithíneachta nó ag blocáil (m.sh. ná déan aschur log UI go díreach ó shnáitheanna oibre).
Tomhais an t-am nuashonraithe deireanach
Má tá an UI “sáinnithe”, d’fhéadfadh sé gur gheall go leor nuashonruithe atá le próiseáil. Tomhais sa snáithe príomha cé chomh minic a dhéanann tú nuashonrú UI in aghaidh an tsoicind agus cé chomh fada a mhaireann sé. Nuair a thógann callbacks UI níos mó ná cúpla milliúiseicind, tá gá le smachtú nó simpliú.
Cathain atá TParallel.For le Progress-UI i ndáiríre tairbheach?
Níl próiseáil chomhthreomhara díreach mar sprioc é féin. Tá sí go háirithe úsáideach nuair a:
- tá na hidirghníomhartha mór go leor (milliúiseicindí go soicindí), ionas go mbíonn an ró-ualach Threadpool íseal,
- tá an tasc trom ar an CPU (parsing, comhbhrú, hashing) nó má tá I/O atá furasta a phara-leagadh (ilchéad comhad, il-HTTP-requests le teorainneacha),
- tá straitéis shoiléir agat do chealú agus do bhainistiú earráidí,
- freastalaíonn na riachtanais UI le dul chun cinn comhdhlúite.
Ní bhíonn sí chomh tairbheach nuair a bhíonn gach idirghníomh an-ghiorra (micre-oidí) nó nuair a rithtear gach idirghníomh chuig an mbacphointe céanna (tráchtáil DB sraitheach, lock domhanda, comhad aonair). Sa chás sin is minic go mbíonn an t-ionsáigh is tapúla: feabhsú algartaim, próiseáil i mbaiscí, laghdú ar rochtain sonraí nó díchumasc go sainráite an bacphointe.
Seicliosta Praicticiúil: Ionas go bhfanfaidh an UI cobhsaí
- Níor cheart an snáithe príomha a bheith blocáilte: gan fanachtí, gan lúbanna fada gan Message Pump.
- Níor chóir do shnáitheanna oibre Controls a láimhseáil: gan rochtain VCL/FMX lasmuigh den snáithe UI.
- Tá nuashonruithe UI smachtaithe: Counter/Timer nó nuashonruithe Queue comhleasa in ionad in aghaidh gach idirghníomh.
- Ná déan glaonna Synchronize laistigh de Locks.
- Tá cealú comh-oibríoch, seiceáilte go minic agus déanann sé glanadh i gceart.
- Bailítear eisceachtaí agus déantar iad a láimhseáil go ordaitheach ag an deireadh.
Conclúid: Dícheangail le Queue, cobhsú trí chomhdhlúthú
Ní thagann comhéadan dul chun cinn iontaofa le TParallel.For trí “Synchronize” a chur áit ar bith; tagann sé ó phrionsabal ailtireachta soiléir: oibríonn na workers go neamhspleách, fanann an Main Thread saor agus próiseálann sé ach cúpla nuashonrú UI tapa. Is é TThread.Queue an uirlis cheart má úsáidtear í go spriocdhírithe agus faoi smacht. Go minic bíonn dhá chúis freagrach as iompar mall nó neamhchobhsaí: bíonn an Main Thread ag fanacht go blocálach áit éigin — nó bíonn sé báite in iomarca nuashonruithe i líne feithimh.
Nuair a bheidh an patrún socraithe i gceart (Counter/Coalescing, Cancel-Flag, Abschluss-Callback), tá sé tairbheach é a chur i bhfeidhm i go leor áiteanna laistigh d’iarratas Delphi atá fásaithe: Import/Export, iniúchtaí sonraí, postanna comhaid agus API — éireoidh gach rud níos freagartha gan tú ag fáil deadlocks nua le gach nuashonrú dul chun cinn.
Má theastaíonn tacaíocht uait chun cód comhthreomhairigh a chobhsú, debugáil a dhéanamh ar chrochtaí an UI, nó iarratais Delphi atá fásaithe a nuachóiriú go glan — déan teagmháil.
Tá Delphi Parallel Programming Library agus Tthread.queue Vs Synchronize tábhachtach don ábhar seo freisin. Cuireann an t-alt na gnéithe seo i gcomhthéacs go soiléir agus léiríonn sé cad atá tábhachtach i ngnáthchleachtas laethúil.
Céim eile
Wenn aus dem Thema ein reales Projekt wird, sollten Architektur, Bestand und Betrieb früh zusammen betrachtet werden.
Ní hamháin go dtacaímid le ceisteanna aonair, ach freisin nuair is gá ó shlisíní cód foinse, ó ábhair legacy nó ó smaointe portail tionscadal corparáideach iontaofa a fhorbairt.
- Measúnítear an staid reatha, an stát sprioc agus na rioscaí teicniúla le chéile.
- REST, Datenzugriff, Portale und Rollout werden nicht als Spätfolgen verschoben.
- Feicfidh sibh go luath cén bealach atá eacnamaíoch agus ó thaobh oibríochta inbhuanaithe.