c# sample - Gibt es einen Unterschied zwischen Lambdas mit und ohne Async deklariert?




2 Answers

Gibt es einen Unterschied zwischen Lambdas mit und ohne Async deklariert?

Ja, es gibt einen Unterschied. Der eine ist ein Async-Lambda und der andere ist nur ein Task-Return-Lambda.

Ein asynchrones Lambda wird in eine Zustandsmaschine kompiliert, während das andere nicht async-lambda eine andere Ausnahmesemantik hat, da Ausnahmen in der zurückgegebenen Aufgabe eingekapselt sind und nicht synchron geworfen werden können.

Es ist genau der gleiche Unterschied wie bei normalen Methoden. Zum Beispiel zwischen dieser asynchronen Methode:

async Task FooAsync()
{
    await DoSomethingAsync("with await");
}

Und diese Aufgabe zurückgebende Methode:

Task FooAsync()
{
    return DoSomethingAsync("no await");
}

Der Blick auf diese Methoden zeigt die Unterschiede deutlicher, aber da Lambdas nur syntaktischer Zucker sind und tatsächlich in Methoden kompiliert werden, die sich genauso verhalten wie diese.

Welches sollten wir bevorzugen und wann?

Das hängt wirklich von deinem Geschmack ab. Wenn Sie das Schlüsselwort async verwenden, wird eine Zustandsmaschine generiert, die weniger performant ist als das einfache Zurückgeben einer Aufgabe. Die Ausnahmesemantik kann jedoch in einigen Fällen überraschend sein.

Nimm diesen Code zum Beispiel:

Hamster hamster = null;
Func<Task> asyncAction = () => FooAsync(hamster.Name);

var task = asyncAction();
try
{
    await task;
}
catch
{
    // handle
}

Würde der try-catch-Block die NullReferenceException oder nicht?

asyncAction nicht, da die Ausnahme beim Aufruf von asyncAction synchron asyncAction . Die Ausnahme wird in diesem Fall jedoch behandelt, da sie in der zurückgegebenen Task erfasst und erneut gestartet wird, wenn diese Task erwartet wird.

Func<Task> asyncAction = async () => await FooAsync(hamster.Name);

Ich persönlich benutze Aufgaben-zurückkehrende Lambdas für diese Ein-Zeilen-Expression-Lambdas, da sie normalerweise ziemlich einfach sind. Aber mein Team verwendet nach ein paar extrem schmerzhaften Fehlern immer die async und await Schlüsselwörter.

assignment function

Gibt es einen Unterschied zwischen lambdas () => DoSomethingAsync() und async () => await DoSomethingAsync() wenn beide als Func<Task> eingegeben werden? Welches sollten wir bevorzugen und wann?

Hier ist eine einfache Konsolen-App

using System;
using System.Threading.Tasks;

namespace asyncDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var demo = new AsyncDemo();
            var task = demo.RunTheDemo();
            task.Wait();

            Console.ReadLine();
        }
    }

    public class AsyncDemo
    { 
        public async Task Runner(Func<Task> action)
        {
            Console.WriteLine(DateTime.Now.ToLongTimeString() + " Launching the action");
            await action();
        }

        private async Task DoSomethingAsync(string suffix)
        {
            await Task.Delay(2000);
            Console.WriteLine(DateTime.Now.ToLongTimeString() + " Done something, " + suffix);
        }

        public async Task RunTheDemo()
        {
            await Runner(() => DoSomethingAsync("no await"));
            await Runner(async () => await DoSomethingAsync("with await"));
        }
    }
}

Die Ausgabe ist:

09:31:08 Launching the action
09:31:10 Done something, no await
09:31:10 Launching the action
09:31:12 Done something, with await

Also in RunTheDemo , beide Anrufe await Runner(someLambda); scheinen dasselbe mit den gleichen Timing-Eigenschaften zu tun - beide haben die richtige Verzögerung von zwei Sekunden.

Beide Linien funktionieren, also sind sie genau gleichwertig? Was ist der Unterschied zwischen den () => DoSomethingAsync() und async () => await DoSomethingAsync() Konstrukten? Welches sollten wir bevorzugen und wann?

Dies ist nicht die gleiche Frage wie "sollte ich im allgemeinen Fall await ", da es sich hier um asynchronen Code handelt, mit Lambdas, die als Func<Task> typisiert sind und die in der konsumierenden Methode korrekt erwartet werden. Die Frage betrifft, wie diese lambdas erklärt werden und welche Auswirkungen diese Erklärung hat.




Ja, sie sind gleich, aber das ist ein ziemlich einfaches Beispiel. Die beiden sind funktional gleichwertig, Sie sind nur (möglicherweise abhängig vom Compiler) mehr Arbeit bei der Verwendung von async .

Ein besserer Fall, um zu sehen, warum async Lambdas nützlich sind, ist, wenn Sie mit einer Folge von asynchronen Operationen fertig werden müssen - das ist es, worauf Sie schließlich await :

await Runner(async () => await DoSomethingAsync(await httpClient.Get("www.google.com")));



Related

c# asynchronous lambda async-await