【问题标题】:PostAsync never returns in console applicationPostAsync 永远不会在控制台应用程序中返回
【发布时间】:2021-03-27 15:43:23
【问题描述】:

我正在尝试实现一个简单的 XML HTTP POST 接口,但不知何故它停止了工作。这是我的代码:

    HttpClient _httpClient = new HttpClient();

    static void Main(string[] args)
    {
        Login("", "");
    }

    public async void Login(string username, string password)
    {
        var response = await SendXml("<foo>");
    }

    public async Task<string> SendXml(string xml)
    {
        var content = new StringContent(xml);
        var response = await _httpClient.PostAsync("http://127.0.0.1:8080/Path", content);
        var responseBody = await response.Content.ReadAsStringAsync();

        return responseBody;
    }

我想说很简单,但是在运行时,它只会停在PostAsync。当我在ReadAsStringAsync 处设置断点时,它永远不会被命中。

我没有例外,没有错误。我的服务器说“发送数据时连接中止”。

我一定是在做一些简单的错误,但我找不到它......我必须说await 的东西仍然让我有点困惑。这段代码是一个控制台应用程序,async/await 会导致这里出现问题吗?

【问题讨论】:

  • 异步/等待不是问题的原因。您是否尝试过指定超时?您是否在调用代码中的任何位置调用 Task.Result?
  • @Silvermind 这可能不是原因,但是当我删除它并使用.Result 时,它工作正常......
  • 不要使用.Result,因为这会导致死锁。
  • 你在使用[StaThread]吗?
  • @Silvermind 控制台应用程序会在收到结果之前结束吗?我将如何等待呢?

标签: c# httpclient


【解决方案1】:

当你使用基于任务的操作时,你需要让你的应用程序一直异步到应用程序的入口点,通常是Program.Main()

如果您使用的是 C# >= 7.1,则可以使用 MainAsync

namespace MyApp
{
    public class Program
    {
        private readonly static HttpClient _httpClient = new HttpClient();
        
        public async static Task Main()
        {
            var response = await SendXml("myxml");
        }

        public async static Task<string> SendXml(string xml)
        {
            var content = new StringContent(xml);
            var response = await _httpClient.PostAsync("http://127.0.0.1:8080/Path", content);
            var responseBody = await response.Content.ReadAsStringAsync();

            return responseBody;
        }
    }
}

如果您使用的是旧版本,则不支持异步入口点,但您可以编写:

namespace MyApp
{
    public class Program
    {
        private readonly static HttpClient _httpClient = new HttpClient();
        
        public static void Main()
        {
            try
            {
                MainAsync().GetAwaiter().GetResult();
            }
            catch (System.Exception)
            {
                // TODO: log unhandled exception
                throw;
            }
        }

        private static Task MainAsync()
        {
            var response = await SendXml("myxml");
        }

        public async static Task<string> SendXml(string xml)
        {
            var content = new StringContent(xml);
            var response = await _httpClient.PostAsync("http://127.0.0.1:8080/Path", content);
            var responseBody = await response.Content.ReadAsStringAsync();

            return responseBody;
        }
    }
}

在最后一种情况下,请确保您只有一个点可以调用 GetAwaiter().GetResult() 而不是其他任何地方,因为这会导致死锁。

【讨论】:

  • 你在catch (Exception) { throw; } 中没有任何意义,因为如果你只是重新抛出它,那就像根本没有抓住一样。
  • @ckuri 我知道。我故意把它放在那里作为操作指南。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-23
  • 2015-05-28
  • 1970-01-01
  • 2020-11-05
  • 2013-10-29
  • 1970-01-01
相关资源
最近更新 更多