Verwenden des Func-Delegaten mit der Async-Methode

71

Ich versuche, Func mit der Async-Methode zu verwenden. Und ich bekomme einen Fehler.

Asynchroner Lambda-Ausdruck kann nicht in Delegatentyp konvertiert werden 'Func<HttpResponseMesage>'. Ein asynchroner Lambda-Ausdruck kann void, Task oder zurückgeben Task<T>, von denen keiner konvertierbar ist 'Func<HttpResponseMesage>'.

Unten ist mein Code:

public async Task<HttpResponseMessage> CallAsyncMethod()
{
    Console.WriteLine("Calling Youtube");
    HttpClient client = new HttpClient();
    var response = await client.GetAsync("https://www.youtube.com/watch?v=_OBlgSz8sSM");
    Console.WriteLine("Got Response from youtube");
    return response;
}

static void Main(string[] args)
{
    Program p = new Program();
    Task<HttpResponseMessage> myTask = p.CallAsyncMethod();
    Func<HttpResponseMessage> myFun =async () => await myTask;
    Console.ReadLine();
}
maxspan
quelle
3
Ich habe einen Blog-Beitrag über asynchrone Delegatentypen , den Sie möglicherweise hilfreich finden.
Stephen Cleary

Antworten:

103

Da der Fehler sagt, Asynchron - Methoden geben Task, Task<T>oder void. Damit dies funktioniert, können Sie:

Func<Task<HttpResponseMessage>> myFun = async () => await myTask;
Spender
quelle
3
Beachten Sie jedoch, dass der asynchrone Vorgang möglicherweise nicht abgeschlossen ist, wenn der Benutzer eine Taste drückt und abgeschlossen Console.ReadLine()ist. Die App könnte beenden , bevor die Asynchron - Operation ist abgeschlossen, wenn Sie nicht ausdrücklich Waitauf dem Task.
Johnathon Sullinger
4

Der Weg , den ich in der Regel nehmen ist , die haben MainMethode invoke ein Run()Verfahren , dass die Rendite einer Aufgabe, und .Wait()auf das Taskzu vervollständigen.

class Program
{
    public static async Task<HttpResponseMessage> CallAsyncMethod()
    {
        Console.WriteLine("Calling Youtube");
        HttpClient client = new HttpClient();
        var response = await client.GetAsync("https://www.youtube.com/watch?v=_OBlgSz8sSM");
        Console.WriteLine("Got Response from youtube");
        return response;
    }

    private static async Task Run()
    {
        HttpResponseMessage response = await CallAsyncMethod();
        Console.ReadLine();
    }

    static void Main(string[] args)
    {
        Run().Wait();
    }
}

Auf diese Weise kann der Rest Ihrer Konsolen-App mit vollständiger Unterstützung für asynchrones Warten / Warten ausgeführt werden. Da eine Konsolen-App keinen UI-Thread enthält, besteht bei der Verwendung von kein Risiko eines Deadlocks .Wait().

Johnathon Sullinger
quelle
1
Dadurch wird die Aufgabe mit Wait () blockiert und es ist nicht mehr die richtige Methode, um einen asynchronen Kontext auszuführen. Bitte lesen Sie eine andere Frage hier
Pimenta
3
Der von Ihnen angegebene Link bezieht sich auf eine MVC-App, bei der Sie korrekt wären. Vor C # 7.2 mussten Sie dies in Konsolen-Apps tun, andernfalls wurde die Konsolen-App ausgeführt und heruntergefahren, bevor Ihr asynchroner Vorgang abgeschlossen wurde. In einer Konsolen-App gibt es keinen SyncContext, über den Sie sich Sorgen machen müssen. Mit C # 7.2 kann Ihre MainMethode jedoch eine asynchrone Aufgabe zurückgeben, damit Sie in einer Konsolen-App warten können.
Johnathon Sullinger
3

Code-Korrektur wie:

static void Main(string[] args)
        {
            Program p = new Program();
            Task<HttpResponseMessage> myTask = p.CallAsyncMethod();
            Func<Task<HttpResponseMessage>> myFun = async () => await myTask;
            Console.ReadLine();
        }
Linh Tuan
quelle
-1

Führen Sie im Func die Aufgabe aus, warten Sie darauf, prüfen Sie sie auf Ausnahmen, und geben Sie dann das Ergebnis zurück.

Func<HttpResponseMessage> myFun = () => 
{
   var t = Task.Run(async () => await myTask);
   t.Wait();
   if (t.IsFaulted)
      throw t.Exception;
   return t.Result;
};
Zohar Chiprut
quelle
Warum wird das abgelehnt? Ich versuche, etwas über asynchrone Programmierung zu lernen, und es würde mir wirklich helfen, das zu wissen.
Eric
1
@Eric - weil es Task.Run () -Mechaniken verwendet, die technisch nicht "asynchron" sind. Es ist eher ein paralleles / gleichzeitiges Konstrukt. Der allgemeine Konsens zwischen asynchron und parallel lautet: asynchron -> E / A-Operationen (denken Sie an Datenbank-, Festplatten- usw. Zugriff) parallel -> CPU-intensive Aufgaben wie die Berechnung einer Fibonacci-Berechnung auf einem großen int
bbqchickenrobot
Sehr hilfreich. Ich mache Hochleistungsrechnen und habe Probleme, gute Muster zu finden, wahrscheinlich weil ich nach asynchronem statt nach parallelem Rechnen gesucht habe.
Eric