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 响应

c#:如何使用 httpclient 发布异步请求并获取流?

C# HTTPClient 不发送请求

如何使用异步发布并使用 HttpClient 等待