Jump to content

SUBIECTE NOI
« 1 / 5 »
RSS
Transferuri instant intre bancile...

player video

Carefur Act for good

Parcare gratis in Bucuresti pentr...
 Rovinieta prin SMS pentru masina ...

Viteza mica Usb 3.2 gen.1 header

Cerificat atestare fiscala pentru...

Schimbare destinatie imobil din l...
 Dorsalgie

Recomandare brand cheie dinamomet...

Divorț la notar

Vechime vs km reali
 Android 12 : "Yahoo Mail s-a ...

Bloc Favorit cu RS2

Ce extractor audio (analogic) pen...

Cine suporta cheltuielile de jude...
 

Task oriented programming in context de multithreading

* * * * * 1 votes
  • Please log in to reply
17 replies to this topic

#1
Rhesus

Rhesus

    Senior Member

  • Grup: Senior Members
  • Posts: 2,882
  • Înscris: 22.04.2014
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
alx42

alx42

    Senior Member

  • Grup: Senior Members
  • Posts: 2,802
  • Înscris: 26.06.2014
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
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,114
  • Înscris: 24.02.2007

View PostRhesus, 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
Rhesus

Rhesus

    Senior Member

  • Grup: Senior Members
  • Posts: 2,882
  • Înscris: 22.04.2014
Î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
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,114
  • Înscris: 24.02.2007
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
Rhesus

Rhesus

    Senior Member

  • Grup: Senior Members
  • Posts: 2,882
  • Înscris: 22.04.2014

View Postdani.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 Posted Image

Edited by Rhesus, 03 November 2019 - 19:05.


#7
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006
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.

View Postdani.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
Rhesus

Rhesus

    Senior Member

  • Grup: Senior Members
  • Posts: 2,882
  • Înscris: 22.04.2014

View PostOriginalCopy, 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
Rhesus

Rhesus

    Senior Member

  • Grup: Senior Members
  • Posts: 2,882
  • Înscris: 22.04.2014
LE: Ideea de aici https://docs.microso...hreading-async/  as aduce-o la nivel de must

#10
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,114
  • Înscris: 24.02.2007

View PostRhesus, 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".

View PostRhesus, 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
Rhesus

Rhesus

    Senior Member

  • Grup: Senior Members
  • Posts: 2,882
  • Înscris: 22.04.2014

View Postdani.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 Posted Image . 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
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,114
  • Înscris: 24.02.2007
Un exemplu de metoda awaitable ce modifica ceva din UI? Suna suspect.

Edited by dani.user, 04 November 2019 - 20:31.


#13
Rhesus

Rhesus

    Senior Member

  • Grup: Senior Members
  • Posts: 2,882
  • Înscris: 22.04.2014
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
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,114
  • Înscris: 24.02.2007
Astfel nu poti accesa in mod direct/simplu elemente UI din DoSomething() sau metode apelate de DoSomething()

#15
Rhesus

Rhesus

    Senior Member

  • Grup: Senior Members
  • Posts: 2,882
  • Înscris: 22.04.2014
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
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,114
  • Înscris: 24.02.2007
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
Rhesus

Rhesus

    Senior Member

  • Grup: Senior Members
  • Posts: 2,882
  • Înscris: 22.04.2014
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. Posted Image

Edited by Rhesus, 05 November 2019 - 19:17.


#18
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,114
  • Înscris: 24.02.2007
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

Bun venit pe Forumul Softpedia!

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

Forumul Softpedia foloseste "cookies" pentru a imbunatati experienta utilizatorilor Accept
Pentru detalii si optiuni legate de cookies si datele personale, consultati Politica de utilizare cookies si Politica de confidentialitate