Dincolo de / pentru I/O, .NET oferă pentru — executarea calculelor pe mai multe nuclee. Distinc principală: / este pentru concurență I/O (așteptări non-blocante), în timp ce , și PLINQ sunt pentru paralelizarea lucrului intensiv pe CPU.
Dincolo de / pentru I/O, .NET oferă pentru — executarea calculelor pe mai multe nuclee. Distinc principală: / este pentru concurență I/O (așteptări non-blocante), în timp ce , și PLINQ sunt pentru paralelizarea lucrului intensiv pe CPU.
asyncawaitasyncawaitTask.RunParallelasync/await → I/O-bound concurrency. Frees the thread during waits (DB, network).
Does NOT add CPU parallelism.
Parallelism → CPU-bound work spread across MULTIPLE CORES (computation, processing).
Use Task.Run, Parallel.For/ForEach, PLINQ.
// run a CPU-intensive computation on a thread pool thread (don't block the caller)
int result = await Task.Run(() => ExpensiveComputation());
// run multiple in parallel and combine
var tasks = items.Select(item => Task.Run(() => Process(item)));
var results = await Task.WhenAll(tasks); // wait for all
Task.Run programează lucrul pe un fir din pool-ul de fire — folosește-l pentru a paraleliza calculele legate de CPU (NU pentru I/O, unde async/await este deja suficient fără fire suplimentare).
// Parallel.For/ForEach — process a collection across cores
Parallel.ForEach(items, item => Process(item)); // automatically uses multiple cores
Parallel.For(0, 1000, i => Compute(i));
// PLINQ — parallel LINQ
var results = data.AsParallel().Where(x => IsValid(x)).Select(Transform).ToList();
Parallel.For/ForEach și PLINQ (.AsParallel()) distribuie automat lucrul pe nuclee — excelente pentru procesarea grea pe CPU a elementelor independente. (Merită doar pentru lucrul cu adevărat legat de CPU, de dimensiuni considerabile — există overhead.)
// parallel code accessing SHARED state needs synchronization or thread-safe types
lock (_lock) { _counter++; } // lock for mutual exclusion
Interlocked.Increment(ref _counter); // lock-free atomic
var dict = new ConcurrentDictionary<string, int>(); // thread-safe collection
Înțelegerea Tasks și a paralelismului dincolo de async/await este cunoaștere importantă de nivel senior pentru construirea aplicațiilor C# performante, iar distinc crucial între concurența legată de I/O și paralelismul legat de CPU este insight-ul cheie — un punct frecvent de confuzie. async/await gestionează concurența legată de I/O (eliberând fire în timpul așteptărilor), dar nu adaugă paralelism legat de CPU, pe când lucrul legat de CPU (calcule, procesare de date) beneficiază de paralelismul real pe nuclee prin Task.Run (descărcarea lucrului CPU pe fire din pool), Parallel.For/ForEach și PLINQ (.AsParallel()).
A ști care instrument se potrivește — async/await pentru I/O, instrumentele TPL de paralelism pentru lucrul legat de CPU — este esențial pentru optimizarea eficace a performanțelor, deoarece folosirea celui greșit (de ex., așteptarea ca async să accelereze calculele, sau pornirea firelor pentru I/O pe care async o gestionează eficient) este ineficace.
Egal de important este să înțelegi siguranța firelor: codul paralel care accesează starea partajată are nevoie de sincronizare (lock, Interlocked pentru operații atomice, sau colecții thread-safe ca ConcurrentDictionary) pentru a evita condițiile de curse — o preocupare critică de corectitudine în codul paralel.
Înțelegerea distinc I/O-vs-CPU, instrumentele de paralelism (Task.Run, Parallel, PLINQ) și cerințele de siguranță a firelor este valoroasă pentru scrierea codului C# concurent și paralel corect și performant.
Deoarece aplicațiile moderne au adesea nevoie atât de concurență I/O cât și de paralelism CPU, iar alegerea abordării corecte și gestionarea corectă a siguranței firelor sunt ceea ce face codul paralel eficace și corect, aceasta este cunoaștere senior importantă și frecvent relevantă pentru dezvoltarea C# sensibilă la performanță.