Benutzer mit den meisten Antworten
Frage zur Funktionsweise der Threads/ Async/ Dispatcher

Frage
-
Ich habe mal eine Frage, wie das ganze mit den Threads in WinRT funktioniert.
So weit ich weiß, laufen immer 2 Threads (zumindest 2 Hauptthreads) der eine ist der UI-Thread, der die UI-aktuell hält und der 2. ist der Arbeitsthread, der die anderen Aufgaben/berechnungen übernimmt.
Stimmt das so? Oder habe ich da was falsch verstanden...
Beim Thema Threading trifft man bei WinRT immer auf 2 Varianten, einmal die Async/Await und die Dispatcher.invoke.
Ich habe jetzt aber noch nicht ganz verstanden was die GENAU machen bzw. funktionieren - habe zwar schon sämtliche dokus durchgelesen, aber stehen immer noch auf dem Schlauch...
Wie ich das verstanden habe:
Bei await/Async wird die Methode bei await unterbrochen und ein neuer Thread erstellt, auf dessen Ergebnis gewartet und dann bei await weitergeführt. Was ist dann der Vorteil, wenn man sowieso wartet, bis der fertig ist?
Bei Dispatcher.invoke wird der für die Ausführung der UI-Thread genutzt.
Vielleicht kann mich jemand etwas aufklären...
Danke für die Antworten...
Antworten
-
Hallo,
dein als erstes wieder gegebenes ist vollkommen richtig.Wenn man das await beim Methodenaufruf weg lässt, wird eben nicht bei der Ausführung gewartet. Angenommen du hast eine asynchrone Methode die ein int (genauer ein Task<int> wegen dem async) zurück gibt:
int x = MyMethod();//Warnung: Beziehen Sie die Verwendung von await in Betracht Console.WriteLine(0);
Je nachdem wie lange MyMethod braucht wird immer 0 ausgegeben. Denn Console.WriteLine wird aufgerufen, bevor MyMethod etwas zurück liefern konnte.
Auch wenn Methoden nichts zurück geben, verrichten Sie trotzdem Arbeit, die in der Richtigen Reihenfolge statt finden muss.
Das ist in den meisten Fällen unerwünscht, weswegen dich der Compiler warnt wenn du das await nicht mit angibst.Wenn du einen weiteren Thread erzeugen willst, solltest du besser die Methoden der Task-Klasse verwenden. Beispielsweise Task.Run(...).
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort vorgeschlagen Aleksander Chalabashiev Montag, 16. März 2015 14:36
- Als Antwort markiert Aleksander Chalabashiev Montag, 23. März 2015 10:41
Alle Antworten
-
Hallo PHep,
als kleine Anmerkung, die Konzepte von WinRT und WPF sind sehr ähnlich, und da du bei WPF mehr Informationenn finden kannst, wäre dort eine Suche sehr empfehlenswert.
Gute Dokumentationen:
- Erstellen reaktionsfähigerer Anwendungen mit dem Dispatcher
- Wikpedia / WPF
- Asynchronous Programming with Async and Await (C# and Visual Basic)
© 2015 Thomas Roskop
Germany // Deutschland
- Bearbeitet Thomas Roskop Samstag, 7. März 2015 21:06
-
Hi,
ein Programm mit nicht thread-sicheren COM-Objekten wie die Windows Oberfläche wird in einem STA (single thread appartment) ausgeführt.The STA model is used for COM objects that are not thread safe. That means they do not handle their own synchronization. A common use of this is a UI component. So if another thread needs to interact with the object (such as pushing a button in a form) then the message is marshalled onto the STA thread. The windows forms message pumping system is an example of this.
If the COM object can handle its own synchronization then the MTA model can be used where multiple threads are allowed to interact with the object without marshalled calls.
Ohne zusätzliche Einstellungen wird eine Windows Anwendung in einem thread ausgeführt. Erst der Einsatz von Background Worker, Threading.Thread, async/await, BeginInvoke, Task... usw. erzeugt separate threads. Um aus den separaten threads Methoden im Context des Haupt-Threads abzuarbeiten wird z.B. Invoke, Dispatcher, Post usw. genutzt. Wenn der Dispatcher genutzt wird, wird die Methode in dem thread ausgeführt, zu dem der Dispatcher gehört.
Bezüglich async/await ist es wirklich so, dass beim await auf das Ende der Ausführung der Methode im anderen thread gewartet wird, falls diese noch nicht beendet wurde. Das ist ein übliches Szenario, z.B. kann eine WebPage erst gerendert werden, wenn die Daten geladen wurden, d.h., es wird parallel das Laden der Daten ausgeführt während andere erforderliche Arbeiten ausgeführt werden.
--
Peter Fleischer
Meine Homepage mit Tipps und Tricks
(MVP, Partner) -
Hallo,
ich möchte Peters Antwort noch um ein Paar Sachen zu async und await ergänzen:Grundsätzlich ist es zunächst so, das jede Anwendung einen Thread hat. Das ist nicht nur in den Windows Store Apps der Fall. Wenn du nun im Hintergrund (beispielsweise im Click-Eventhandler eines Buttons) eine Aufgabe ausführst, wird für diese Zeit die GUI blockiert.
Um das zu verhindern muss man einen 2. Thread anlegen. Bei Eventhandlern ist es dabei möglich ein async in die Methodendeklaration zu hängen:private async void Button_Click(object sender, RoutedEventArgs e)
Das hat zur Folge, dass alles in der Methode in einem 2. Thread ausgeführt wird und die GUI weiterhin funktioniert.
Wenn du nun eine Methode aufrufst, die asynchron ist (sprich async verwendet), solltest du diese mit await aufrufen:
await MyMethod();
Wenn man das await weg lässt, würde wieder ein neuer Thread angelegt werden und MyMethod würde wieder asynchron laufen. Das await sorgt nun dafür, dass MyMethod im selben Thread ausgeführt wird.
Das Aufrufen mit await funktioniert nur bei Methoden die Task oder Task<T> zurück geben. Das ist ein relativ häufig gemachter Fehler bei eigenen, asynchronen Methoden wenn diese einfach void zurück geben. Das heißt dann nämlich, dass die Methode immer in einem 2. Thread ausgeführt wird. Das ist lediglich bei Eventhandlern so gewählt, weswegen man dort async void stehen hat.Wie eingangs erwähnt läuft die GUI immer im selben Thread. Wenn man nun also auf ein Control zugreifen will, muss der Hintergrundthread mit dem GUI-Thread synchronisiert werden. Das übernimmt in diesem Fall der Dispatcher. Würdest du ihn nicht bekommen, erhältst du entsprechend eine Exception wegen einem Threadübergreifenden Zugriff.
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets -
Also hier noch mal einfach niedergeschrieben was mir so grad durch den Kopf geht...
Also dient der Dispatcher hauptsächlich dafür, um aus einem asynchronen Thread heraus das UI zu aktualisieren...
Und das await async ist "nur" dafür da, um das UI nicht zu blockieren... Durch das await wir also der 2. asynchroneThread synchornisiert, in dem er auf dessen Ende wartet und dann erst weiter gemacht. Der 2. Thread ist deswegen wichtig, weil sonst für die Zeit der Ausführung das UI blockieren würde!
Was würde aber genau passieren, wenn ich das await weg lasse? Der Thread würde asynchron laufen, das wäre aber doch nicht weiter schlimm, weil ich das Ergebnis doch trotzdem in variablen speichern oder mit dem Dispatcher das UI aktualisieren könnte...
Wie ist das, wenn ich Prozesse beschleunigen möchte (Multithreading) dann muss ich wahrscheinlich backgroundworker einsetzen o.ä.?!
-
Hallo,
dein als erstes wieder gegebenes ist vollkommen richtig.Wenn man das await beim Methodenaufruf weg lässt, wird eben nicht bei der Ausführung gewartet. Angenommen du hast eine asynchrone Methode die ein int (genauer ein Task<int> wegen dem async) zurück gibt:
int x = MyMethod();//Warnung: Beziehen Sie die Verwendung von await in Betracht Console.WriteLine(0);
Je nachdem wie lange MyMethod braucht wird immer 0 ausgegeben. Denn Console.WriteLine wird aufgerufen, bevor MyMethod etwas zurück liefern konnte.
Auch wenn Methoden nichts zurück geben, verrichten Sie trotzdem Arbeit, die in der Richtigen Reihenfolge statt finden muss.
Das ist in den meisten Fällen unerwünscht, weswegen dich der Compiler warnt wenn du das await nicht mit angibst.Wenn du einen weiteren Thread erzeugen willst, solltest du besser die Methoden der Task-Klasse verwenden. Beispielsweise Task.Run(...).
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort vorgeschlagen Aleksander Chalabashiev Montag, 16. März 2015 14:36
- Als Antwort markiert Aleksander Chalabashiev Montag, 23. März 2015 10:41