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();
}

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;

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().


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();
        }

-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;
};

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.