103

I am trying to use Func with Async Method. And I am getting an error.

Cannot convert async lambda expression to delegate type 'Func<HttpResponseMesage>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<HttpResponseMesage>'.

below is my 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();
}
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
maxspan
  • 13,326
  • 15
  • 75
  • 104
  • 7
    I have a blog post on [async delegate types](http://blog.stephencleary.com/2014/02/synchronous-and-asynchronous-delegate.html) that you may find helpful. – Stephen Cleary May 17 '16 at 17:38
  • The code seems to have a bug:`Error CS4010 Cannot convert async lambda expression to delegate type 'Func'. An async lambda expression may return void, Task or Task, none of which are convertible to 'Func'.` The correct one must be `Func> myFun =async () => await myTask;` – Code Pope May 31 '21 at 17:48

4 Answers4

145

As the error says, async methods return Task,Task<T> or void. So to get this to work you can:

Func<Task<HttpResponseMessage>> myFun = async () => await myTask;
spender
  • 117,338
  • 33
  • 229
  • 351
  • 4
    Just be aware that the async operation might not be completed by the time the user presses a key, and `Console.ReadLine()` is done. The app could terminate before the async operation is finished, unless you explicitly `Wait` on the `Task`. – Johnathon Sullinger May 17 '16 at 15:46
5

The path I usually take is to have the Main method invoke a Run() method that returns a Task, and .Wait() on the Task to complete.

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

This allows the rest of your Console app to run with full async/await support. Since there isn't any UI thread in a console app, you don't run the risk of deadlocking with the usage of .Wait().

Johnathon Sullinger
  • 7,097
  • 5
  • 37
  • 102
  • 2
    This will block the Task with the Wait() and it is not the correct way to do async context anymore. Please read another question [here](https://stackoverflow.com/questions/13140523/await-vs-task-wait-deadlock) – Pimenta May 30 '19 at 17:17
  • 4
    The link you provide is for a MVC app, where you would be correct. Prior to C# 7.2, this was what you had to do in console apps, otherwise the console app finished executing and shut down before your async operation completed. There isn’t any SyncContext to worry about in a Console app. However, C# 7.2 lets your `Main` method return an async Task so you can await in a console app. – Johnathon Sullinger May 31 '19 at 00:59
3

Code fix such as:

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
  • 440
  • 3
  • 11
-2

Inside the Func run the task, wait for it and check for exception, then return the result.

Func<HttpResponseMessage> myFun = () => 
{
   var t = Task.Run(async () => await myTask);
   t.Wait();
   if (t.IsFaulted)
      throw t.Exception;
   return t.Result;
};
Zohar Chiprut
  • 752
  • 1
  • 8
  • 18
  • why is this voted down? I am trying to learn about async programming and it would really help me to know that. – Eric Oct 09 '20 at 14:58
  • 2
    @Eric - because it's using Task.Run() mechanichs which isn't technically "async". Its more of a parallel/conccurrent construct. The general consensus on async vs parallel is this: async -> I/O operations (think db, disk, etc access) parallel -> CPU intensive tasks such as computing a fibonacci calculation on a large int – bbqchickenrobot Oct 14 '20 at 22:07
  • Very helpful. I'm doing high performance computing and I have been having trouble finding good patterns, probably because I have been searching for async instead of parallel computing. – Eric Oct 15 '20 at 01:25