mit dem folgenden Code ...Wie konvertiere ich dies in eine asynchrone Aufgabe?
static void DoSomething(int id) {
Thread.Sleep(50);
Console.WriteLine(@"DidSomething({0})", id);
}
Ich weiß, dass ich dies zu einer async Aufgabe umwandeln kann wie folgt ...
static async Task DoSomethingAsync(int id) {
await Task.Delay(50);
Console.WriteLine(@"DidSomethingAsync({0})", id);
}
Und das von so tun, wenn ich mehrere Male nenne (Task.WhenAll) wird alles schneller und effizienter als vielleicht mit Parallel.Foreach oder sogar von innerhalb einer Schleife aufrufen.
Aber für eine Minute, lassen Sie uns vortäuschen, dass Task.Delay() nicht existiert, und ich muss tatsächlich Thread.Sleep(); Ich weiß in der Realität, dass dies nicht der Fall ist, aber das ist Konzept-Code und wo die Verzögerung/Sleep ist normalerweise eine IO-Operation, wo es keine Async-Option (wie frühe EF).
Ich habe versucht, die folgenden ...
static async Task DoSomethingAsync2(int id) {
await Task.Run(() => {
Thread.Sleep(50);
Console.WriteLine(@"DidSomethingAsync({0})", id);
});
}
Aber, obwohl es ohne Fehler läuft, nach Lucien Wischik dies ist in der Tat eine schlechte Praxis, da sie lediglich Fäden aus dem Pool hochgefahren wird jede Aufgabe abzuschließen (es ist auch langsamer die folgende Konsole-Anwendung - wenn Sie tauschen zwischen DoSomethingAsync und DoSomethingAsync2 nennen Sie einen signifikanten Unterschied in der Zeit sehen können, dass es in Anspruch nimmt) ...
static void Main(string[] args) {
MainAsync(args).Wait();
}
static async Task MainAsync(String[] args) {
List<Task> tasks = new List<Task>();
for (int i = 1; i <= 1000; i++)
tasks.Add(DoSomethingAsync2(i)); // Can replace with any version
await Task.WhenAll(tasks);
}
ich dann folgendes versucht. ..
static async Task DoSomethingAsync3(int id) {
await new Task(() => {
Thread.Sleep(50);
Console.WriteLine(@"DidSomethingAsync({0})", id);
});
}
Wenn Sie dies anstelle des ursprünglichen DoSomethingAsync übertragen, wird der Test nie abgeschlossen, und auf dem Bildschirm wird nichts angezeigt!
Ich habe auch mehrere andere Varianten ausprobiert, die entweder nicht kompilieren oder nicht abgeschlossen werden!
Mit der Einschränkung, dass Sie keine vorhandenen asynchronen Methoden aufrufen können und sowohl die Thread.Sleep als auch die Console.WriteLine in einer asynchronen Task ausführen müssen, wie geht das auf eine Weise, die so effizient wie das Original ist Code?
Das Ziel für diejenigen von Ihnen, die interessiert sind, ist es, mir ein besseres Verständnis zu geben, wie ich meine eigenen asynchronen Methoden erstellen kann, wo ich niemanden anrufe. Trotz vieler Suchen scheint dies der einzige Bereich zu sein, in dem Beispiele wirklich fehlen - während es viele tausend Beispiele für den Aufruf asynchroner Methoden gibt, die andere asynchrone Methoden aufrufen, finde ich keine, die eine existierende void-Methode in eine asynchrone Aufgabe konvertieren Es gibt keinen weiteren Aufruf für eine asynchrone Task außer denen, die die Methode Task.Run (() => {}) verwenden.
Ihr letztes Beispiel wird nie abgeschlossen, weil Sie nie schaffen Sie die Aufgabe 'Starten' nennen. – Lee
@lee: Wenn ich auf neue Aufgabe (() => {}) warte, wird Start() nicht kompiliert, weil Task.Start() void zurückgibt. –
Wenn Sie effizient warten müssen, ohne Threads zu blockieren, können Sie stattdessen [TaskCompletionSource] (http://msdn.microsoft.com/en-us/library/dd449174.aspx) verwenden. – Lee