Task oriented programming in context de multithreading
#1
Posted 03 November 2019 - 03:31
Voi porni de la aceasta intrebare, dar reformulata corect
https://stackoverflo...es-it-make-appl Răspunsul e simplu: Nu asincronitatea in sine "face" o aplicație sa fie responsive, ci posibilitatea de a face await pe ceva care, în definița lui, creează un alt thread. (adică să nu ruleze pe UI) Cum știm bine că async-await nu creează alte thread-uri, ci oferă o viziune de programare sincronă pe ceva ce este, in fapt, asincron (adică ușurează munca programatorului...), am două dileme: 1. Totuși, de ce nu menționează nimeni faptul că utilizarea async-await are sens/rost doar dacă Task-ul pe care facem await, în definiția lui, creează un nou thread? Sau, mai corect spus, faptul că thread-ul de unde se face await diferă de cel din interiorul funcției. Pentru că altfel, rezultatul este identic ca în varianta sincronă, doar mecanismul este diferit: public async Task MyTask() { var t = await DoSomethingThatTakes10seconds(); } Dacă nu am garanția că în DoSomethingThatTakes10seconds() se creează un nou thread, atunci thread-ul apelant al lui MyTask (care poate fi UI thread de ex.) tot se blochează. În varianta sincronă se blochează la locul apelului, iar in cea asincronă - MyTask returnează imediat, dar degeaba pentru că ... (înțelegeți ideea). Pentru asta, avem probabil un await Task.Run() undeva in DoSomethingThatTakes10seconds() ... 2. In documentația MSDN, chiar dacă rutinele care facilitează programarea asincronă au sufixul Async asta nu garantează ceea ce am spus la punctul 1. În afară de "fler, logică și firesc”, cine ne garantează că o rutină cu o denumire sugestivă (să zicem un fictiv GetFromUrlAsync(), DownloadFromUrlAsync()) face, sau nu, toată treabă pe un alt thread? Pentru că altfel ..... (pct. 1). Ne asiguram ca rulam noi pe un thread nou cu Task.Run().... Daca nu stim ce are in spate metoda XAsync(), dar totusi ne dorim sa ruleze pe un alt thread: a. Se creeaza un thread (cel creat de noi cu Task.Run()) - daca in mod natural XAsync() nu porneste un alt thread. b. Vom avea doua thread-uri (cel creat de noi cu Task.Run(), si respectiv un ipotetic thread creat de dezvoltatorul metodei). Și aici e puțină risipă... Edited by Rhesus, 03 November 2019 - 03:45. |
#2
Posted 03 November 2019 - 11:06
e normal ca async-await sa nu fie multi-threaded implicit, si sa fie responsabilitatea ta sa faci mai multe fire de executie.
daca ar fi multithreaded implicit, la nivel de limbaj, ar aparea alte probleme.. de ex. race-conditions. |
#3
Posted 03 November 2019 - 12:17
Rhesus, on 03 noiembrie 2019 - 03:31, said: ci posibilitatea de a face await pe ceva care, în definița lui, creează un alt thread. (adică să nu ruleze pe UI) De unde necesitatea asta de a avea neaparat alt thread? Raspunsul il gasesti chiar pe stackoverflow, sub raspunsul selectat: cand ai I/O procesorul e notificat asincron cand s-a terminat o operatie. Iar operatiile I/O sunt principalele surse de metode async intalnite in .NET. |
#4
Posted 03 November 2019 - 14:38
În cazul async I/O se trimite un request cãtre kernel, iar thread-ul apelant este notificat de cãtre acesta atunci când operația I/O s-a finalizat. Cã operația dureazã 10-20-30 secunde - nu ne intereseazã - nu doar datoritã mecanismului de asincronitate ci în special faptului cã este implicat kernel-mode - adicã task-ul în sine nu se realizeazã pe firul curent. (vorbim de o altã entitate)
Gresesc? Nu știu cum sã mã exprim. Vreau sã spun cã atunci când facem await pe ceva (consumator de timp si de resurse), trebuie sã ai garanția cã acel ceva nu are legãturã cu thread-ul curent. Nu mã refer strict la async I/O. La modul general vorbesc, la utilitatea async/await. Edited by Rhesus, 03 November 2019 - 14:46. |
#5
Posted 03 November 2019 - 18:22
async/await e syntactic sugar (poti inspecta in ce se transforma codul dupa compilare) pentru a nu folosi callbacks. Inainte de async/await primeai un Task si apoi continuai cu Task.ContinueWith(...)
Garantie ca MetodaAsync() pe care o apelezi nu iti va bloca UI nu cred ca poti avea. Tine pana la urma de bunul simt al celor ce au scris metoda. Daca blocatul UI-ul e cea mai mare grija, sa nu uitam de batranul BackgroundWorker. |
#6
Posted 03 November 2019 - 19:04
dani.user, on 03 noiembrie 2019 - 18:22, said:
async/await e syntactic sugar (poti inspecta in ce se transforma codul dupa compilare) pentru a nu folosi callbacks. Inainte de async/await primeai un Task si apoi continuai cu Task.ContinueWith(...) Garantie ca MetodaAsync() pe care o apelezi nu iti va bloca UI nu cred ca poti avea. Tine pana la urma de BUNUL SIMT al celor ce au scris metoda. Daca blocatul UI-ul e cea mai mare grija, sa nu uitam de batranul BackgroundWorker. Bingo. Aici voiam sa ajung Edited by Rhesus, 03 November 2019 - 19:05. |
#7
Posted 04 November 2019 - 12:53
Habar n-am despre ce vorbesc (nu sunt .net guy), dar dacă am înțeles corect, intrebarea e
De ce compilatorul te lasă să folosești await într-o metodă care e deja async? 1:1 așa cum ai postat tu codul e o problemă ușor de rezolvat. Dar e dificil când acel await se află in spatele mai multor apeluri, ar trebui o analiză completă a call graph la compilare, lucru care poate să nici nu fie posibil dacă c# oferă lucruri de genul "shared library", lucru pe care probabil îl și face. dani.user, on 03 noiembrie 2019 - 18:22, said:
Garantie ca MetodaAsync() pe care o apelezi nu iti va bloca UI nu cred ca poti avea. Tine pana la urma de bunul simt al celor ce au scris metoda. Deci garanția se numește code review. |
#8
Posted 04 November 2019 - 15:48
OriginalCopy, on 04 noiembrie 2019 - 12:53, said:
Habar n-am despre ce vorbesc (nu sunt .net guy), dar dacă am înțeles corect, intrebarea e De ce compilatorul te lasă să folosești await într-o metodă care e deja async? [...] Deci garanția se numește code review. Nu. async-ul doar specifică faptul că metoda poate returna (”o promisiune”/ la fel ca obiectul Promise din Javascript - conceptual vorbind) la locului await-ului + faptul că ”revine” o dată ce task-ul asteptat s-a finalizat. Dacă nu avem await in metodă, nu e nici o problemă, compilatorul doar te avertizează că metoda va rula sincron (nefiind niciun await inauntru). Ca si cum nu ar fi acolo ”keyword-ul”. Ca apa sființită... Problema pusă de mine se regăsește la partea de code review (cum ai menționat). Sau, atunci când îți crapă aplicația (sau se blochează mai mult timp) și nu știi de ce ... Păi de ce? Că ai făcut await pe un task, degeaba, că ăla tot pe firul curent lucrează. Și dacă bug-ul e în task ... aleluia! (ps. bineînțeles, când task-ul nu e creat de tine ...). Așa că m-am obișnuit ca intotdeauna atunci cand vreau să fac await pe o rutină, în acea rutină creez eu un thread nou - pentru că, scopul final e să nu-mi blocheze firul principal, sau, dacă e o rutină din bibliotecă: await Task.Run(async () => metodaXAsync()); All in all, ideea asincronității e foarte bună, ușurează mult munca programatorului. Dar încă nu este destul de matură, sau hai să zicem ”pe jumătate”. Edited by Rhesus, 04 November 2019 - 16:03. |
#9
Posted 04 November 2019 - 16:12
LE: Ideea de aici https://docs.microso...hreading-async/ as aduce-o la nivel de must
|
#10
Posted 04 November 2019 - 19:44
Rhesus, on 04 noiembrie 2019 - 15:48, said:
Nu. async-ul doar specifică faptul că metoda poate returna (”o promisiune”/ Nu chiar. Nu te opreste nimeni sa returnezi un Task fara async/await. async in declaratia metodei zice doar ca va fi "reorganizata". Rhesus, on 04 noiembrie 2019 - 15:48, said:
Așa că m-am obișnuit ca intotdeauna atunci cand vreau să fac await pe o rutină, în acea rutină creez eu un thread nou - pentru că, scopul final e să nu-mi blocheze firul principal, sau, dacă e o rutină din bibliotecă: await Task.Run(async () => metodaXAsync()); Cam pesimista solutia. Ai patit de multi ori sa dai peste metode ce returneaza Task dar care sa blocheze? E foarte posibil ca ele sa ruleze in unele situatii sincron (ex. se citeste ceva din cache si raspunsul e dispoinibil adesea imediat). |
|
#11
Posted 04 November 2019 - 20:24
dani.user, on 04 noiembrie 2019 - 19:44, said:
Cam pesimista solutia. Ai patit de multi ori sa dai peste metode ce returneaza Task dar care sa blocheze? E foarte posibil ca ele sa ruleze in unele situatii sincron (ex. se citeste ceva din cache si raspunsul e dispoinibil adesea imediat). Păi cam asta aș evita . Nu vreau să ”pățesc”. De la premiza asta pornesc când programez. Bineînțeles, singura dată când, în mod intenționat nu creez un thread nou e atunci când metoda awaitable modifică ceva ce are legătură cu UI-ul. De ex. o proprietate care e legată de UI. Și atunci, asta e, lucrez pe thread-ul de UI, cu f. mare atenție (eventual cronometrez să văd cate ms îi ia task-ului să ,,se termine”). Dar e foarte bună intrebarea ta. Edited by Rhesus, 04 November 2019 - 20:31. |
#12
Posted 04 November 2019 - 20:31
Un exemplu de metoda awaitable ce modifica ceva din UI? Suna suspect.
Edited by dani.user, 04 November 2019 - 20:31. |
#13
Posted 04 November 2019 - 20:42
Uite, asta vreau sa evit:
private async void UIButton_Click(object sender, RoutedEventArgs e) { await DoSomething(); } private async Task DoSomething() { await SomethingElse(); Task.Delay(5000).Wait(); } private async Task SomethingElse() { .... } PS. Scuze pentru indentare. Ideea e ca din event handler eu apelez, de buna credinta, asincron DoSomething(). Nu am garantia ca inauntru nu am o tampenie (in cazul de fata Wait()-ul ala de 5 secunde, care imi blocheaza thread-ului meu). Si pentru asta, fac: private async void UIButton_Click(object sender, RoutedEventArgs e) { await Task.Run(async()=> await DoSomething()); // ... } 1. Am garantia ca nu imi blocheaza thread-ul principal, ruland pe thread pool. 2. Pot gestiona mai bine aplicatia. Edited by Rhesus, 04 November 2019 - 20:55. |
#14
Posted 04 November 2019 - 21:15
Astfel nu poti accesa in mod direct/simplu elemente UI din DoSomething() sau metode apelate de DoSomething()
|
#15
Posted 04 November 2019 - 21:28
Da. Asta e adevarat. Inauntru folosesc Dispatcher.RunAsync() doar atunci cand modific elemente UI. Restul subtask-urilor, le las pe un thread secundar. Alea se pot bloca, pot face ce vor.
Fiind un subiect de discutii, chiar va rog sa veniti cu sugestii, eventual - daca procedez bine sau nu. Si revenind la rutinele din .NET, tocmai de asta ma "plangeam": Momentan, asincronitatea rezolva pe jumatate munca programatorului. Iar comportamentul multor rutine (chiar si asincrone) e imprevizibil (rutine din biblioteci ma refer). Iti poate bloca sau nu aplicatia .... Edited by Rhesus, 04 November 2019 - 21:34. |
|
#16
Posted 04 November 2019 - 21:42
Cum multe biblioteci moderne din lumea .NET sunt opensource, prefer sa verific sursa daca am dubii. N-am intalnit inca biblioteci populare care sa zica Async dar sa blocheze. Am intalnit unele ce nu ofera async peste tot (lipsea si async din nume) dar astea-s cazuri particulare ce se pot ajusta cu extension methods de exemplu.
Edited by dani.user, 04 November 2019 - 21:43. |
#17
Posted 05 November 2019 - 19:07
Ca o paralelă, în Android:
https://developer.an...id/os/AsyncTask An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. [...] The steps: [...] 2. doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. Implementarea din Android mi se pare mai firească. Defapt, tocmai la asta mă refeream, fără să știu că în Android e așa cum îmi imaginam private class MyTask extends AsyncTask<...> { protected T doInBackground() { ... } protected void onprogressUpdate() { ... } protected void onPostExecute(T param) { // showDialog(...); or any UI-related method } } doInBackground e analogul task-ului pe care se face await in .NET onPostExecute() acționează asupra return-ului task-ului - imediat ce e "gata": adică ce făceam noi cu var t = await doInBackground() - din .NET Android-ul imi garantează că doInBackground() nu-mi va bloca UI-ul. Edited by Rhesus, 05 November 2019 - 19:17. |
#18
Posted 05 November 2019 - 20:13
Garantarea asta pesimista costa. Cum in lumea Java nu prea ai API-uri asincrone iar lumea e obisnuita sa creeze threaduri la tot pasul, e oarecum fireasca solutia lor.
|
Anunturi
▶ 0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users