为何C#中API里的Fire-and-Forget模式在HTTP调用时失效?
三个Minimal API行为差异的原因解析
接收端API代码
var app = builder.Build(); app.MapGet("/testing", () => { Console.WriteLine("Received"); }); app.Run();
这是一个普通的接收请求API,只要收到/testing路径的请求,就会打印"Received"日志。
未发起HTTP调用的调用端API代码
var app = builder.Build(); app.MapGet("/call", () => { using var client = new HttpClient(); client.GetAsync("http://localhost:5215/testing"); }); app.Run();
为什么没发起调用却返回200?
GetAsync是异步方法,但这里没有加await,代码只会创建一个异步任务,不会等待它执行完成就继续往下走。using var client声明的HttpClient,会在当前API处理方法执行完毕后立刻被释放。而这个处理方法是同步的,执行到client.GetAsync这行后马上就结束了,HttpClient提前被释放,导致刚创建的异步请求直接被终止,实际没发起有效的HTTP调用。- 因为API处理方法同步执行完毕,所以直接给客户端返回200状态码。
延迟5秒发起调用的调用端API代码
var app = builder.Build(); app.MapGet("/call", () => { Task.Run(async () => { await Task.Delay(5000); using var client = new HttpClient(); await client.GetAsync("http://localhost:5215/testing"); }); }); app.Run();
为什么返回200后5秒会发起调用?
Task.Run把内部的异步委托放到了后台线程池执行,和当前API的处理线程完全分离。- 当前API处理方法执行完
Task.Run这一行就直接结束了,所以立刻给客户端返回200状态码。 - 后台的异步委托会独立运行:先等待5秒,然后创建HttpClient,这里用
await等待GetAsync执行完成,所以HttpClient会在请求结束后才被释放,不会提前终止请求,因此5秒后能成功发起HTTP调用。
内容的提问来源于stack exchange,提问作者user33276346
相关产品推荐
相关产品推荐

