Ich fange an, in C # 5.0 etwas über Async / Warten zu lernen, und ich verstehe es überhaupt nicht. Ich verstehe nicht, wie es für Parallelität verwendet werden kann. Ich habe das folgende sehr grundlegende Programm ausprobiert:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Task task1 = Task1();
Task task2 = Task2();
Task.WaitAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
}
}
Dieses Programm blockiert nur den Aufruf von Task.WaitAll()
und wird nie beendet, aber ich verstehe nicht warum. Ich bin sicher, ich vermisse nur etwas Einfaches oder habe einfach nicht das richtige mentale Modell dafür, und keiner der Blogs oder MSDN-Artikel, die es gibt, hilft.
c#
async-await
Alex Marshall
quelle
quelle
await new Task....
Verwenden Sie stattdessenawait Task.Delay(...);
Antworten:
Ich empfehle Ihnen, mit meiner Einführung in
async
/await
und der offiziellen MSDN-Dokumentation zu TAP zu beginnen .Wie ich in meinem Intro-Blog-Beitrag erwähne, gibt es mehrere
Task
Mitglieder, die Überbleibsel der TPL sind und keine Verwendung in reinemasync
Code haben.new Task
undTask.Start
sollte durchTask.Run
(oderTaskFactory.StartNew
) ersetzt werden. EbensoThread.Sleep
sollte durch ersetzt werdenTask.Delay
.Schließlich empfehle ich, dass Sie nicht verwenden
Task.WaitAll
; Ihre Konsolen-App sollte nurWait
auf einer einzigen AppTask
verwendet werdenTask.WhenAll
. Mit all diesen Änderungen würde Ihr Code folgendermaßen aussehen:class Program { static void Main(string[] args) { MainAsync().Wait(); } public static async Task MainAsync() { Task task1 = Task1(); Task task2 = Task2(); await Task.WhenAll(task1, task2); Debug.WriteLine("Finished main method"); } public static async Task Task1() { await Task.Delay(5000); Debug.WriteLine("Finished Task1"); } public static async Task Task2() { await Task.Delay(10000); Debug.WriteLine("Finished Task2"); } }
quelle
Main
eine Ausnahme von der Richtlinie "Nicht blockieren" darstellt. Aber ich ziehe es vor, den außergewöhnlichen Code (mitWait
) von jeder Logik zu trennen , zu der ich geheMainAsync
. Es ist nur so viel weniger wahrscheinlich, dass Sie einen Deadlock erleiden, wenn Sie diesen Code in eine GUI- oder ASP.NET-App kopieren / einfügen.SynchronizationContext
. WPF (und ich glaube WinRT) müssen nichts Besonderes tun; Ihr VorhandenseinSynchronizationContext
reicht aus, damit sichasync
Event-Handler korrekt verhalten. Ich erkläre die Erfassung / Wiederaufnahme des Kontexts in meinem Intro-Beitrag und habe auch einen MSDN-Artikel , derSynchronizationContext
ausführlich behandelt wird, wenn Sie ihn interessant finden.Verstehen Sie C # Task, asynchron und warten Sie
C # Aufgabe
Die Task-Klasse ist ein asynchroner Task-Wrapper. Thread.Sleep (1000) kann einen laufenden Thread für 1 Sekunde stoppen. Während Task.Delay (1000) die aktuelle Arbeit nicht stoppt. Siehe Code:
public static void Main(string[] args){ TaskTest(); } private static void TaskTest(){ Task.Delay(5000); System.Console.WriteLine("task done"); }
Beim Ausführen wird sofort "Aufgabe erledigt" angezeigt. Ich kann also davon ausgehen, dass jede Methode aus Task asynchron sein sollte. Wenn ich TaskTest () durch Task.Run (() => TaskTest ()) ersetze, wird die erledigte Aufgabe erst angezeigt, wenn ich eine Console.ReadLine () anhänge. nach der Run-Methode.
Intern repräsentiert die Task-Klasse einen Thread-Status in einer Zustandsmaschine. Jeder Zustand in der Zustandsmaschine hat mehrere Zustände wie Start, Verzögerung, Abbrechen und Stopp.
asynchron und warten
Nun fragen Sie sich vielleicht, ob alle Aufgaben asynchron sind. Was ist der Zweck von Task.Delay? Lassen Sie uns als Nächstes den laufenden Thread mithilfe von Async wirklich verzögern und warten
public static void Main(string[] args){ TaskTest(); System.Console.WriteLine("main thread is not blocked"); Console.ReadLine(); } private static async void TaskTest(){ await Task.Delay(5000); System.Console.WriteLine("task done"); }
async tell caller, ich bin eine asynchrone Methode, warte nicht auf mich. Warten Sie im TaskTest () und fragen Sie nach dem Warten auf die asynchrone Aufgabe. Nach dem Ausführen wartet das Programm nun 5 Sekunden, um den Text für die erledigte Aufgabe anzuzeigen.
Aufgabe abbrechen
Da Task eine Zustandsmaschine ist, muss es eine Möglichkeit geben, die Task abzubrechen, während die Task ausgeführt wird.
static CancellationTokenSource tokenSource = new CancellationTokenSource(); public static void Main(string[] args){ TaskTest(); System.Console.WriteLine("main thread is not blocked"); var input=Console.ReadLine(); if(input=="stop"){ tokenSource.Cancel(); System.Console.WriteLine("task stopped"); } Console.ReadLine(); } private static async void TaskTest(){ try{ await Task.Delay(5000,tokenSource.Token); }catch(TaskCanceledException e){ //cancel task will throw out a exception, just catch it, do nothing. } System.Console.WriteLine("task done"); }
Wenn das Programm ausgeführt wird, können Sie jetzt "stop" eingeben, um die Verzögerungsaufgabe abzubrechen.
quelle
Ihre Aufgaben werden nie beendet, weil sie nie ausgeführt werden.
Ich würde
Task.Factory.StartNew
eine Aufgabe erstellen und starten.public static async Task Task1() { await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(5))); Debug.WriteLine("Finished Task1"); } public static async Task Task2() { await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(10))); Debug.WriteLine("Finished Task2"); }
Nebenbei bemerkt, wenn Sie wirklich nur versuchen, eine asynchrone Methode anzuhalten, müssen Sie nicht einen ganzen Thread blockieren, sondern nur verwenden
Task.Delay
public static async Task Task1() { await Task.Delay(TimeSpan.FromSeconds(5)); Debug.WriteLine("Finished Task1"); } public static async Task Task2() { await Task.Delay(TimeSpan.FromSeconds(10)); Debug.WriteLine("Finished Task2"); }
quelle
Async und Warten sind Markierungen, die Codepositionen markieren, von denen aus die Steuerung nach Abschluss einer Aufgabe (eines Threads) fortgesetzt werden soll. Hier ist ein detailliertes Youtube-Video, das das Konzept auf demonstrative Weise erklärt: http://www.youtube.com/watch?v=V2sMXJnDEjM
Wenn Sie möchten, können Sie auch diesen Artikel über das Coodeprojekt lesen, in dem dies auf visuellere Weise erklärt wird. http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:- "Async" und "Await" (Codemarkers)
quelle