使用带有 Async 方法的 Func 委托

我正在尝试用异步方法使用 Func。我得到了一个错误。

无法将异步 lambda 表达式转换为委托类型 'Func<HttpResponseMesage>'。异步 lambda 表达式可以返回 void、 Task 或 Task<T>,它们都不能转换为 'Func<HttpResponseMesage>'

以下是我的守则:

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();
}
119182 次浏览

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;

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

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

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