C# HttpClient 无需等待响应即可发布信息
Posted
技术标签:
【中文标题】C# HttpClient 无需等待响应即可发布信息【英文标题】:C# HttpClient to post information without waiting for response 【发布时间】:2016-03-23 22:05:26 【问题描述】:我在我的 asp.net web api 2 应用程序中使用HttpClient 类将一些信息发布到端点。我只想发布信息而不等待回复。 这是正确的语法吗
using (var client = new HttpClient())
client.BaseAddress = new Uri("http://localhost:9000/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP POST
var gizmo = new Product() Name = "Gizmo", Price = 100, Category = "Widget" ;
var response = await client.PostAsJsonAsync("api/products", gizmo);
【问题讨论】:
您是否试图摆脱“等待”?你会收到一个警告,但也许是你要求的...... 不回答您的问题。但我认为值得分享。我正在使用 FLurl 并喜欢它。 github.com/tmenier/Flurl 您是从 ASP.NET WebApi 应用程序调用HttpClient
吗?
@marco.marinangeli:我想知道我的做法是否正确?如果我删除 await
关键字,我会收到以下消息 because this call is not awaited execution of the current method continues before the call is completed
@YuvalItzchakov:我正在从一个 asp.net web api 服务调用另一个 asp.net web api 服务。
【参考方案1】:
我只想发布信息而不等待回复
不等待 WebAPI 中的异步方法将导致运行时异常,因为 AspNetSynchronizationContext
知道任何触发的异步操作。如果它在异步操作之前注意到控制器操作完成,它将触发所述异常。更多关于ASP.NET Controller: An asynchronous module or handler completed while an asynchronous operation was still pending
如果您想使用火而忘记语义,如果您使用的是 .NET 4.5.2 及更高版本,则需要通过 HostingEnvironment.QueueBackgroundWorkItem
将委托排队。如果没有,你可以推迟使用BackgroundTaskManager
请记住,这种设计并不真正适合 WebAPI。如果您经常触发此操作调用,它不会扩展。如果这种方式经常发生,请考虑使用更合适的方式,例如消息代理。
【讨论】:
这不是问题的答案。可以只 POST 到服务器并终止 HTTP/TCP 连接。无论如何,服务器可以并且通常会继续请求。PostAsync
可能不是这里的解决方案,如果它总是读取响应。
@makhdumi 这不是我想说的。由于 OP 希望从 ASP.NET 执行此操作,他需要知道运行时知道无人看管的任务,并且会导致对用户的响应返回错误代码而不是正确完成。
OP 说“我只想发布信息而不等待回复。”这里的问题是HttpClient.PostAsync
会自动读取响应流。如果只想发送数据而不需要读取响应,则实际上不需要任何异步或非异步操作来读取请求流(即等待服务器响应)。这与 QueueBackgroundWorkItem
的“一劳永逸”不同。您的回答完全有道理,您关于可扩展性的观点完全成立,即使只是发送响应,但并不是问题的真正答案。
@makhdumi OP 说“不等待回复”,而不是“不阅读回复”*。您会建议什么替代方案?
我的意思是,无论哪种方式,您都在等待PostAsync
的回复,例如在另一个线程中。就像您说的那样,这根本不是可扩展的,因为您可以轻松获得大量线程等待响应。这可以通过简单地不在任何线程中等待/读取响应来避免。【参考方案2】:
要在 ASP.NET 中实现异步任务,请参考以下示例语法:
protected void Page_Load(object sender, EventArgs e)
try
RegisterAsyncTask(new PageAsyncTask(LoadUrlContent));
catch
protected async Task LoadUrlContent()
try
// Add your code here, for example read the content using HttpClient:
string _content = await ReadTextAsync(YourUrl, 10);
catch throw;
另外,在页面级别设置<%@ Page ... Async="true" %>
。
下面的示例代码sn-p展示了HttpClient的使用(从LoadUrlContent()
调用这个示例函数:
protected async Task<string> ReadTextAsync(string Url, int TimeOutSec)
try
using (HttpClient _client = new HttpClient() Timeout = TimeSpan.FromSeconds(TimeOutSec) )
_client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/html"));
using (HttpResponseMessage _responseMsg = await _client.GetAsync(Url))
using (HttpContent content = _responseMsg.Content)
return await content.ReadAsStringAsync();
catch throw;
您可以根据您的特定任务修改此代码库。
希望这会有所帮助。
【讨论】:
我的应用是asp.net web api。我正在使用 HttpClient 发布信息。您提供的答案不使用 HttpClient 类。 请参考使用 HttpClient 的扩展答案/示例代码。最好的问候, 感谢您的快速回复。但我不想阅读回复。我只想开火然后忘记。此外,我正在从一个 asp.net web api 应用程序调用另一个 asp.net web api 应用程序。 那么您可以尝试 Task.Run() 因为 async/await 与“即发即弃”有点对立(根据定义它正在等待某些东西)。不过,您可以使用 ConfigureAwait(false) 来获得理想的结果。最好的问候,以上是关于C# HttpClient 无需等待响应即可发布信息的主要内容,如果未能解决你的问题,请参考以下文章
C# Xamarin 没有收到来自 HttpClient 的响应
C# 使用 HttpClient 从 JSON 响应中获取特定对象
如何在 C# 中使用 HttpClient 读取 Web api 响应