La necessità del .NET Framework 3.5 è legata alla presenza di Parallel Language Integrated Query (PLINQ), il paradigma dichiarativo di codice parallelo che permette allo sviluppatore di esprimere cosa vuole ottenere piuttosto che come, direttamente derivato dalle caratteristiche uniche al mondo di LINQ. PLINQ viene esposto dal namespace System.Linq contenuto nell'assembly System.Threading.dll, che andrà referenziato in ogni progetto.
Alle funzionalità di PLINQ si accede in due modi. Il primo è tramite la classe System.Linq.ParallelEnumerable, che espone un'implementazione concorrente dei medesimi metodi esposti nel core da un'enumeration LINQ. Per fissare le idee, una query su una collection System.Linq.Enumerable viene effettuata, in LINQ, dal seguente codice:
<span style="font-size:1.0em">
IEnumerable data = ...;
var q = Enumerable.Select(
Enumerable.OrderBy(
Enumerable.Where(data, x => p(x)),
x => k(x)),
x => f(x));
foreach (var e in q) a(e);
</span>
<span style="font-size:1.0em">
IEnumerable data = ...;
var q = ParallelEnumerable.Select(
ParallelEnumerable.OrderBy(
ParallelEnumerable.Where(data, x => p(x)),
x => k(x)),
x => f(x));
foreach (var e in q) a(e);
</span>
La seconda sintassi trae vantaggio dagli extensions methods di C# 3.0, e si applica in maniera naturale alla sintassi compatta delle query LINQ. La stessa query di cui sopra poteva essere espressa nella seguente forma:
<span style="font-size:1.0em">
IEnumerable data = ...;
var q = data.Where(x => p(x)).Orderby(x => k(x)).Select(x => f(x));
foreach (var e in q) a(e);
</span>
<span style="font-size:1.0em">
IEnumerable data = ...;
var q = data.AsParallel().Where(x => p(x)).Orderby(x => k(x)).Select(x => f(x));
foreach (var e in q) a(e);
</span>
<span style="font-size:1.0em">
Public Shared Function Scramble( _
ByVal words As String()) As String()
Return (From word In words _
Select ScrambleWord(word)).ToArray()
End Function
</span>
<span style="font-size:1.0em">
Public Shared Function Scramble( _
ByVal words As String()) As String()
Return (From word In words.AsParallel() _
Select ScrambleWord(word)).ToArray()
End Function
</span>
<span style="font-size:1.0em">
Public Shared Function Scramble( _
ByVal words As String()) As String()
Return (From word In words.AsParallel( _
<b>ParallelQueryOptions.PreserveOrdering</b>)_
Select ScrambleWord(word)).ToArray()
End Function
</span>
A dispetto della sua incredibile potenza espressiva, esistono degli scenari, legati alla presenza di codice legacy che fa uso del parallelismo imperativo di dati e task e che è necessario migrare, in cui PLINQ è una soluzione efficace, ma non ottima; per tali casi (dai quali è esclusa ogni applicazione già sviluppata facendo uso di LINQ) le Parallel Extensions for .NET Framework espongono la Task Parallel Library ed i suoi due namespace, System.Threading e System.Threading.Tasks, contenuti anch'essi nell'assembly System.Threading.dll.