edit
Task Parallel Library
- Task Parallel Library ist ein moderner Thread-Pool in .NET
Threading in .NET
- Thread nimmt delegate entgegen
Thread myThread = new Thread(() => {
for (int i = 0; i < 100; i++) {
Console.WriteLine("MyThread step {0}", i);
}
});
myThread.Start();
// ...
myThread.Join();
- Unbehandelte Exceptions in einem Thread führen zum Abbruch des Programms!
Monitor
class BankAccount {
private decimal balance;
private object syncObject = new object();
public void Withdraw(decimal amount) {
lock(syncObject) {
while (amount > balance) {
Monitor.Wait(syncObject);
}
balance -= amount;
}
}
public void Deposit(decimal amount) {
lock(syncObject) {
balance += amount;
Monitor.PulseAll(syncObject); // wie notifyAll()
}
}
}
- Monitor hat im Gegensatz zu Java Fairness (FIFO Queue)
Task Parallel Library
- Work stealing thread pool (singleton)
- Verschiedene Abstraktionsstufen
- Task Parallelization: Explizite Tasks starten
- Data Parallelization: Parallele Statements und Queris
- Asynchrone Programmierung mit Continuation style
Task Parallelisierung
Task task = Task.Run(() => {
// task implementation
});
// perform other activity
task.Wait(); // Blockiert, bis Task beendet wird
- Tasks können weitere Tasks starten
Task.Run(() => {
Task<int> left = Task.Run(() => Count(leftPart));
Task<int> right = Task.Run(() => Count(rightPart));
int result = left.Result + right.Result;
});
- Anzahl Worker-Threads wird variiert
- Es wird "ausprobiert" und der Durchsatz gemessen
- Wenn der Durchsatz besser wird, werden die Anzahl Threads erhöht
- Bei einem Deadlock kann der Pools immer weiter wachsen
Datenparallelität
- Unabhängige Statements und Loops können parallel ausgeführt werden
Parallel.Invoke(
() => MergeSort(l, m),
() => MergeSort(m, r)
);
Parallel.ForEach(list,
file => Convert(file)
);
- blockiert, bis alle Tasks fertig sind
- TPL gruppiert die "Bodies" automatisch in Tasks, es wird nicht zwingend für jede Iteration einen eigenen Task erstellt
- Partitionierung kann fix angegeben werden
Parallel.ForEach(Partitioner.Create(0, array.Length),
(range, _) => {
for (int i = range.Item1; i < range.Item2; i++) {
DoCalculation(array[i]);
}
});
Parallel LINQ
- Parallele Verarbeitung von Collection Operationen
- Oft können Conditions parallel geprüft werden
ParallelQuery<Book> query =
from book in bookCollection.AsParallel()
where book.Title.Contains("Concurrency")
select book;
query.ForAll(b => {
if (Interesting (b)) {
Read(b);
}
});
- Resultat hat beliebige Reihenfolge,
ForAll
wird auch in beliebiger Reihenfolge ausgeführt
- Für richtige Reihenfolge noch
AsOrdered()
anhängen (Performance-Einbussen)
- Geht in Java auch mit
parallelStream()
, dort ist der output aber standardmässig geordnet
- Achtung vor Seiteneffekten in Query!
Asynchrone Programmierung
- Tasks starten und auf Resultat warten
var task = Task.Run(
LongOperation
);
// perform other work
int result = task.Result;
- Task Continuations wie bei Java
task1.ContinueWith(task2).ContinueWith(task3)
- Multi-Continuation
Task.WhenAll(task1, task2).ContinueWith(task3)
Asynchronität in C#
- Sprachkonstrukt in C# für asynchrone Ausführung
- Thema nächste Woche