Ud over / til I/O leverer .NET til — kørsel af beregninger på tværs af flere kerner. Den vigtige forskel: / er til I/O-concurrency (ikke-blokerende ventetid), mens , og PLINQ er til parallelisering af CPU-intensive arbejdsopgaver.
Ud over / til I/O leverer .NET til — kørsel af beregninger på tværs af flere kerner. Den vigtige forskel: / er til I/O-concurrency (ikke-blokerende ventetid), mens , og PLINQ er til parallelisering af CPU-intensive arbejdsopgaver.
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 planlægger arbejde på en thread pool-tråd — brug det til at parallelisere CPU-bound beregning (IKKE til I/O, hvor async/await allerede er tilstrækkeligt uden ekstra tråde).
// 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 og PLINQ (.AsParallel()) distribuerer automatisk arbejde over kerner — fantastisk til CPU-tungt arbejde med uafhængige elementer. (Kun værd det for genuint CPU-bound, betydningsfuldt arbejde — der er 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
At forstå Tasks og parallelisme ud over async/await er vigtig senior-level viden til at bygge performant C#-applikationer, og den afgørende forskel mellem I/O-concurrency og CPU-parallelisme er den vigtigste indsigt — et almindeligt forvirringssted. async/await håndterer I/O-bound concurrency (frigiver tråde under ventetid), men tilføjer ikke CPU-parallelisme, hvorimod CPU-bound arbejde (beregninger, databehandling) drager fordel af faktisk parallelisme på tværs af kerner via Task.Run (offloading af CPU-arbejde til thread pool-tråde), Parallel.For/ForEach og PLINQ (.AsParallel()).
At vide, hvilket værktøj der passer — async/await til I/O, TPL-parallelisme-værktøjerne til CPU-bound arbejde — er essentielt for effektiv ydeoptimering, da brug af det forkerte værktøj (f.eks. at forvente, at async fremskynder beregning, eller at oprette tråde til I/O, som async håndterer effektivt) er ineffektivt.
Ligeledes vigtig er forståelsen af trådssikkerhed: parallel kode, der får adgang til delt tilstand, har brug for synkronisering (lock, Interlocked til atomare operationer, eller trådsikre samlinger som ConcurrentDictionary) for at undgå race conditions — en kritisk correctness-bekymring i parallel kode.
At forstå I/O-vs-CPU-forskellen, parallelisme-værktøjerne (Task.Run, Parallel, PLINQ) og trådsikkerhedskravene er værdifuld for at skrive korrekt, performant concurrent og parallel C#.
Da moderne applikationer ofte har brug for både I/O-concurrency og CPU-parallelisme, og da valg af den rigtige tilgang og korrekt håndtering af trådssikkerhed er det, der gør parallel kode effektiv og korrekt, er dette vigtig, hyppigt relevant senior viden for ydelses-sensitiv C#-udvikling.