74
Threading mit C# Threading C# Workshop, TU Darmstadt 2008, Präsentation von Qiong Wu (Microsoft Junior Student Partner)

C# Workshop - Threading

Embed Size (px)

DESCRIPTION

That's the slides for our C# Workshop at Darmstadt University of Technology, powered by Microsoft Student Partners.

Citation preview

Page 1: C# Workshop - Threading

Threading mit C#Threading

C# Workshop, TU Darmstadt 2008, Präsentation von Qiong Wu (Microsoft Junior Student Partner)

Page 2: C# Workshop - Threading

Threading heute

Page 3: C# Workshop - Threading

Todo:

Prozesse / Threads? Arbeiten mit Threads Erstellen von Threads Threads beenden Datenzugriff mit Threads Deadlocks ThreadPools Asnychrone Programmierung Timer Windows Forms & Threading

Page 4: C# Workshop - Threading

Prozesse

Ablaufende Programme Heißen unter Windows auch Tasks Erlauben einem Prozessor mehrere

Aufgaben „gleichzeitig“ zu bearbeiten Interprozesskommunikation Besitzen

Virtuellen Adressspeicher Ausführbaren Code Mindestens einen Ausführungsthread

Page 5: C# Workshop - Threading

Prozesse managen: Der Task Manager

Page 6: C# Workshop - Threading

Threads

Teilbereiche eines Prozesses Erlauben einem Prozess mehrere

Aufgaben „gleichzeitig“ zu bearbeiten.

Teilen sich virtuellen Adressspeicher und die Systemressourcen des Prozesses zu dem sie gehören

C# Programme starten automatisch Hauptthread

Page 7: C# Workshop - Threading

Prozesse vs. Threads

Beides Konzepte zur parallelen Programmierung

Prozesse sind unabhängige Ausführungseinheiten

Threads als logische Arbeitsteile eines Prozesses

Parallelisierung sowohl mit mehreren Prozessen als auch mehreren Threads theoretisch möglich

Page 8: C# Workshop - Threading

Over-Multi Process Coordination

Page 9: C# Workshop - Threading

Over-Multithreading

Page 10: C# Workshop - Threading

Standardfall

Page 11: C# Workshop - Threading

Nutzen für Programmierer?

Parallelisieren von Programmaufgaben

Nutzen von Multi-Threaded Hardware (Multicore, Multiprozessor)

Trennung von Benutzeroberfläche und Berechnung

Verteilte Systeme

Page 12: C# Workshop - Threading

Wann keine Threads benutzen?

Threads können die Performance beeinträchtigen (Thread Overhead)

Threads sind häufige Fehlerquellen Viele Threads bedeuten auch viel

Ärger Ergo: Threading nur dann einsetzen

wenn es sinnvoll ist!

Page 13: C# Workshop - Threading

Threading in C#.net

Multithreading in C# relativ einfach Unterstützt asynchrones und

synchrones Threading Wichtigstes Werkzeug:

System.Threading Namespace

Page 14: C# Workshop - Threading

Arbeiten mit Threads

Manuelles Erstellen von Threads Beenden von Threads Datenzugriffe koordinieren Asynchrone Programmierung ThreadPool verwenden

Page 15: C# Workshop - Threading

Erstellen von Threads

1. Methode für Threadeinstiegspunkt erstellen

2. ParametrizedThreadStart / ThreadStart Delegaten mit Verweis auf die Einstiegsmethode erstellen

3. Thread Objekt mit Delegaten erstellen

4. Optional: Threadeigenschaften festlegen

5. Thread starten

Page 16: C# Workshop - Threading

ParametrizedThreadStart / ThreadStart Delegate

ThreadStart für parameterlose Threadmethoden

ParametrizedThreadStart für Threadmethoden mit Parameter Parameter muss vom Typ object sein

Page 17: C# Workshop - Threading

Auszuführende Methode

static void Main(string[] args) { ThreadStart TestThreadStart = new ThreadStart(ThreadMethod); Thread TestThread = new Thread(TestThreadStart);

TestThread.Name = "Test Thread"; TestThread.Priority = ThreadPriority.Normal; TestThread.IsBackground = false;

TestThread.Start();

Console.ReadLine(); } static void ThreadMethod() { Console.WriteLine("Thread Run"); }

Threadoptionen

Beispiel: Parameterloser Thread

Kein Rückgabewert

Page 18: C# Workshop - Threading

Auszuführende Methode

static void Main(string[] args) { ParameterizedThreadStart TestThreadStart = new ParameterizedThreadStart(ThreadMethod); Thread TestThread = new Thread(TestThreadStart);  TestThread.Name = "Test Thread"; TestThread.Priority = ThreadPriority.Normal; TestThread.IsBackground = false;  TestThread.Start("Test");  Console.ReadLine(); }  static void ThreadMethod(object Parameter) { Console.WriteLine("Thread Run with Parameter: " + Parameter.ToString()); }

Threadoptionen

Beispiel: Parametrisierter Thread

Start mit Parameter

Kein Rückgabewert object Parameter

Page 19: C# Workshop - Threading

Warten auf Threads

Unterscheidung zwischen Foreground Threads Background Threads

Thread.Join()

Page 20: C# Workshop - Threading

Beispiel: Foreground & Background Threads

Thread ForegroundThread = new Thread(new ThreadStart(ThreadMethod)); ForegroundThread.Start();

Thread BackgroundThread = new Thread(new ThreadStart(ThreadMethod)); BackgroundThread.IsBackground = true; BackgroundThread.Start();

Foreground Thread Verhindert Beenden

der Applikation

Background Thread kann nach

Beendigung aller Foreground Threads terminiert werden

Page 21: C# Workshop - Threading

Beispiel: Thread.Join

ThreadStart operation = new ThreadStart(ThreadMethod); Thread[] theThreads = new Thread[5]; for (int x = 0; x <= 4; ++x) { theThreads[x] = new Thread(operation); theThreads[x].Start(); } foreach (Thread oneThread in theThreads) { Console.WriteLine("Waiting for Thread to terminate"); oneThread.Join(); Console.WriteLine("Thread terminated"); }

Auf Threadende warten

Thread starten

Page 22: C# Workshop - Threading

Threadpriorität

Bestimmt die Vorrangregelung bei der Ausführung eines Threads

Thread.Priority Eigenschaft ThreadPriority Enum

Lowest BelowNormal Normal AboveNormal Highest

Page 23: C# Workshop - Threading

Beispiel: Threadpriorität

Thread NormalPriorityThread = new Thread(new ThreadStart(ThreadMethod)); Thread HighPriorityThread = new Thread(new ThreadStart(ThreadMethod)); HighPriorityThread.Priority = ThreadPriority.Highest;

NormalPriorityThread.Start(); HighPriorityThread.Start();

Standardpriorität ist ThreadPriority.Normal

Setzen der Threadpriorität auf

ThreadPriority.Highest

Page 24: C# Workshop - Threading

Threads beenden

Thread.Abort() Löst ThreadAbortException aus Beendet Thread nach Auslösen der

Exception Sicheres Beenden von Threads

ThreadAbortException behandeln Alternative: Abortvariable

Page 25: C# Workshop - Threading

Beispiel: Thread.Abort()

static void Main(string[] args) { Thread newThread = new Thread(new ThreadStart(ThreadMethod)); newThread.Start(); Thread.Sleep(1000); newThread.Abort(); Console.ReadLine(); }

Thread beenden

Page 26: C# Workshop - Threading

Beispiel: ThreadAbortException

static void ThreadMethod() { try { for (int i = 0; i < 100; i++) { Console.WriteLine("Thread - working."); Thread.Sleep(100); } } catch (ThreadAbortException e) { Console.WriteLine("Thread - caught ThreadAbortException - resetting."); Console.WriteLine("Exception message: {0}", e.Message); } finally { Console.WriteLine("Just one more message before I drop"); }

}

ThreadAbortException behandeln

Page 27: C# Workshop - Threading

Alternative: Abortvariable

Einige Programmieren raten von Thread.Abort ab

Gründe Thread.Abort kann Thread an jeder Stelle

abbrechen Finally Statements können übergangen

werden Ressourcen können ungeschlossen

bleiben Ansatz: Abortvariable einführen und

im Thread pollen

Page 28: C# Workshop - Threading

Beispiel: Abortvariable

static void TestManualAbort() { Thread newThread = new Thread(new ThreadStart(ManualAbortThreadMethod)); newThread.Start(); Thread.Sleep(1000); Abort = true; } static volatile bool Abort = false; static void ManualAbortThreadMethod() { while (true) { if (Abort == false) { Console.WriteLine(System.DateTime.Now.ToString()); } else { break; } } }

Page 29: C# Workshop - Threading

Anmerkung

Probleme mit Thread.Abort() lassen sich auch ohne Abortvariable umgehen

Alternative Lösungen Code auf ThreadAbortException

anpassen Constrained Execution Regions einsetzen

(Fortgeschritten)

Page 30: C# Workshop - Threading

Fragen?Oder einfach Pause?

Page 31: C# Workshop - Threading

Datenzugriffe koordinieren

Vor Multithreading: Nur ein gleichzeitiger Zugriff auf Daten

Mit Multithreading: Möglichkeit des gleichzeitigen Zugriffs auf Daten von mehreren Threads

Was passiert wenn mehrere Threads gleichzeitig einen Datenbestand manipulieren?

Page 32: C# Workshop - Threading

Problem: Race Condition

Mehrere Threads können eine gemeinsame Variable manipulieren

Probleme beim Rückschreiben von Werten

Fehlerhafte Werte als Ergebnis

Page 33: C# Workshop - Threading

Beispiel: Race Condition

Thread 2X = X + 15

X = 0

Thread 1X = X + 30

Variable einlesen Variable einlesen

Page 34: C# Workshop - Threading

Beispiel: Race Condition

Thread 2X=0

X = 0

Thread 1X=0

Page 35: C# Workshop - Threading

Beispiel: Race Condition

Thread 2X=0

X = 0

Thread 1X=30

Page 36: C# Workshop - Threading

Beispiel: Race Condition

X = 0

Thread 1X=30

Variable schreiben

Thread 2X=15

Page 37: C# Workshop - Threading

Beispiel: Race Condition

X = 30

Thread 1Beenden…

Thread 2X=15

Variable schreiben

Page 38: C# Workshop - Threading

Beispiel: Race Condition

X = 15

Thread 2Beenden…

Page 39: C# Workshop - Threading

Beispiel: Race Condition

X = 15

Page 40: C# Workshop - Threading

Lösung des Problems

Interlocked Klasse Synchronisierungssperren

Page 41: C# Workshop - Threading

Interlocked Klasse

Bietet atomare Operationen für Variablen

Nur für triviale Operationen an einer Variable (Addieren, Dekrementieren, Vertauschen, Inkrementieren)

Effektiv, aber beschränktes Einsatzgebiet

Page 42: C# Workshop - Threading

Synchronisierungssperren

Monitor.Enter() + Monitor.Exit() Lock Schlüsselwort ReaderWriterLock Mutex / Semaphore / AutoResetEvent

/ ManualResetEvent

Page 43: C# Workshop - Threading

Monitor.Enter() / Monitor.Exit()

Setzt in Codeabschnitt eine Synchronisierungssperre

Synchronisieren auf ein Objekt Besitzer des Monitor des Objekts erhält

exklusiven Zugriff auf Codeabschnitt Andere blockieren bis Freigabe des

Monitors

Page 44: C# Workshop - Threading

Lock Schlüsselwort

Synchronisierungsobjekt als Parameter

Umschließt Codebereich implizit mit Monitor.Enter() und Monitor.Exit()

Page 45: C# Workshop - Threading

Beispiel: Monitor.Enter() / Monitor.Exit()

public static object Lockvar = new object(); public static void LockMethod(object Parameter) { Monitor.Enter(Lockvar); try { count++; Console.WriteLine("Thread " + count + " Writing"); finally { Monitor.Exit(Lockvar); } }

Sperrvariable

Anfang Synchronisierungssperr

e

Ende Synchronisierungssperr

e

Page 46: C# Workshop - Threading

Beispiel: Lock Schlüsselwort

public static object Lockvar = new object(); public static void LockMethod(object Parameter) { lock (Lockvar) { count++; Console.WriteLine("Thread " + count + " Writing"); } }

Sperrvariable

Sperrvariable

Page 47: C# Workshop - Threading

Deadlocks

Zwei Threads schließen sich gegenseitig durch Synchronisationssperren aus

Thread A wartet auf Thread B, Thread B wartet auf Thread A

Endloses Warten

Page 48: C# Workshop - Threading

Beispiel: Deadlocks

public static object Lockvar1 = new object(); public static object Lockvar2 = new object(); public static void DeadLockMethodOne() { lock (Lockvar1) { lock (Lockvar2) { Console.WriteLine("First"); } } } public static void DeadLockMethodTwo() { lock (Lockvar2) { lock (Lockvar1) { Console.WriteLine("Second"); } } }

Sperrvariable

Sperrt Lockvar1

Sperrt Lockvar2

Page 49: C# Workshop - Threading

Lösung?

Sorgfältig Programmieren! Monitor.TryEnter() mit Zeitlimit Kurze Codeabschnitte sperren

Page 50: C# Workshop - Threading

ReaderWriterLock

ReaderWriteLock Klasse ermöglicht Ausschließliche Lesesperre Schreibsperre Wechsel von Lese zu Schreibsperre und

vice versa

Page 51: C# Workshop - Threading

Fragen?Oder noch eine Pause?

Page 52: C# Workshop - Threading

ThreadPool

Erstellung eigener Threads oft unnötig

ThreadPool verwaltet Threads die auf Abruf bereit stehen, Standardanzahl 25

Overhead bei Threaderstellung und Threadvernichtung eliminiert

ThreadPool Threads sind Hintergrundthreads

ThreadPool Arbeitsaufgaben können nicht durch Fremdeinwirkung abgebrochen werden

Page 53: C# Workshop - Threading

Arbeiten mit ThreadPool

ThreadPool.QueueUserWorkItem Übergabe von Verweis auf Funktion Optional: Übergabe von Parameter

ThreadPool.GetMaxThreads Anzahl der maximal verfügbaren

Threads abrufen ThreadPool.SetMaxThreads

Anzahl der maximal verfügbaren Threads festlegen

Page 54: C# Workshop - Threading

Thread in ThreadPool erstellen

WaitCallback workItem = new WaitCallback(ThreadMethod);

if (!ThreadPool.QueueUserWorkItem(workItem, "ThreadPooled")) { Console.WriteLine("Element konnte nicht in Warteschlange gestellt werden"); }

WaitCallback DelegateThread mit Parameter

starten

Page 55: C# Workshop - Threading

Asynchrone Programmierung Idee: Asynchrones Starten & Beenden eines

Ablaufs Vorteile

Keine manuelle Verwaltung des Threads notwendig Automatische Threadskalierung Performancegewinn durch automatische Nutzung

von ThreadPool 3 Verwendungsmodelle

Warten-bis-fertig Modell Pollingmodell Rückrufmodell

Page 56: C# Workshop - Threading

Warten-bis-fertig Modell

Asynchrone Operation starten Andere Arbeiten erledigen Mit EndXXX auf Ende der Operation

warten

Page 57: C# Workshop - Threading

Beispiel: Warten bis fertig Modell

Console.WriteLine("Start Async Fetchin.."); GenericMethodDelegate<int> method = IntFetcher.Fetch; IAsyncResult ar = method.BeginInvoke(null, method);

Thread.Sleep(1000);

Console.WriteLine("Got " + method.EndInvoke(ar)); Console.WriteLine("End Async Fetchin..");

Methode asynchron ausführen

Andere Arbeiten ausführen

Auf Ende der Methode warten

Page 58: C# Workshop - Threading

Pollingmodell

Starten der asnychronen Operation Regelmäßig überprüfen ob die

Operation abgeschlossen ist Nach Abgeschlossener Operation

EndXXX aufrufen

Page 59: C# Workshop - Threading

Beispiel: Pollingmodell

Console.WriteLine("Start Async Fetchin.."); IAsyncResult ar2 = method.BeginInvoke(null, method);

while (!ar2.IsCompleted) { Thread.Sleep(1000); }

Console.WriteLine("Got " + method.EndInvoke(ar2)); Console.WriteLine("End Async Fetchin..");

Methode asynchron ausführen

Andere Arbeiten ausführen

Regelmäßig pollen

Ergebnis abrufen (keine Wartezeit)

Page 60: C# Workshop - Threading

Rückrufmodell

Starten der asynchronen Operation mit Übergabe einer Rückruffunktion

Page 61: C# Workshop - Threading

Beispiel: Rückrufmodell

Console.WriteLine("Start Async Fetchin.."); IAsyncResult ar3 = method.BeginInvoke(new AsyncCallback(CompleteFetch), method);

Thread.Sleep(1000);

static void CompleteFetch(IAsyncResult result) { GenericMethodDelegate<int> method = (GenericMethodDelegate<int>)result.AsyncState; int i = method.EndInvoke(result); Console.WriteLine("Got " + i); Console.WriteLine("End Async Fetchin..."); }

Ergebnis abrufen (keine Wartezeit)

Andere Arbeiten ausführen

Callback Funktion angeben

Page 62: C# Workshop - Threading

Fehlerbehandlung

Try Catch bei Aufruf der EndXXX Methode anwenden

try { Console.WriteLine("Got " + method.EndInvoke(ar2)); } catch { Console.WriteLine("Error occured"); } finally { Console.WriteLine("End Async Fetchin.."); }

Page 63: C# Workshop - Threading

Asynchrone Methoden implementieren

Delegaten erstellen BeginInvoke des Delegaten aufrufen EndInvoke des Delegaten aufrufen

Page 64: C# Workshop - Threading

Beispiel: Asynchrone Methoden implementieren

public delegate TOutput GenericMethodDelegate<TOutput>();

static void TestAsync() { Console.WriteLine("Start Async Fetchin.."); GenericMethodDelegate<int> method = IntFetcher.Fetch; IAsyncResult ar = method.BeginInvoke(null, method); Thread.Sleep(1000); Console.WriteLine("Got " + method.EndInvoke(ar)); Console.WriteLine("End Async Fetchin.."); }

Delegat auf auszuführende

Methode

Methode dem Delegat zuweisen

Methode asynchron starten

Blockieren bis asynchrone Methode

beendet

Page 65: C# Workshop - Threading

System.Threading.Timer

Ruft eine Methode asynchron nach Zeitspanne auf

Wiederholt Aufruf der Methode nach Zeitspanne

Timer.Change

Page 66: C# Workshop - Threading

Beispiel: Threading.Timer

static void TestTimer() { Timer tm = new Timer(new TimerCallback(ThreadMethod), "Timer", 0, 1000); Thread.Sleep(1000); tm.Change(0, 100); }

TimerCallbackDelegate

Parameter

Tick Intervall

Startverzögerung

Intervall / Verzögerung ändern

Page 67: C# Workshop - Threading

Windows Forms & Threading

Häufigster Anwendungsfall für Threading: Rechenlast aus GUIs auslagern

Dem Hauptthread möglichst wenig Rechenlast zuordnen

Rechenlast in Hauptthread verursacht hängende GUIs

Problematik: Zugriff auf Steuerelemente von Threads aus

Page 68: C# Workshop - Threading

Threaded vs Unthreaded

private void cmdThreaded_Click(object sender, EventArgs e) { Thread FormsThread = new Thread(new ThreadStart(DoWork)); FormsThread.Start(); }

private void cmdUnthreaded_Click(object sender, EventArgs e) { DoWork(); }

Page 69: C# Workshop - Threading

Ausführung von komplexen Operationen im GUI Thread

Page 70: C# Workshop - Threading

HowNotTo: Direktes Manipulieren

private void button1_Click(object sender, EventArgs e) { Thread FormsThread = new Thread(new ThreadStart(ManipulateList)); FormsThread.Start(); }

private void ManipulateList() { listBox1.Items.Add("test"); }

Page 71: C# Workshop - Threading

Ungültiger Vorgang!

Page 72: C# Workshop - Threading

Lösung: Invoke Method

Direktes Manipulieren von Windows Forms Steuerelementen löst Exception aus

Mit Invoke den UI Thread auffordern Manipulationen vorzunehmen

Delegaten übergeben Asynchroner Aufruf ebenfalls möglich Optional: Eine Methode für Invoke

und Direkt mit InvokeRequired Eigenschaft

Page 73: C# Workshop - Threading

Beispiel: Invoke

private delegate void ManipulateListDelegate();

private void ManipulateList() { if (listBox1.InvokeRequired == true) { listBox1.Invoke(new ManipulateListDelegate(ManipulateList)); } else { listBox1.Items.Add("test"); } }

Delegat nach Funktion erstellen

Invoke benötigt?

Invoke aufrufen mit Verweis auf Methode

Manipulationen vornehmen

Page 74: C# Workshop - Threading

Fragen?