C#HttpClient - PostAsync不返回(即使使用ConfigureAwait)

Mom*_*omo 1 c# wpf httpclient blocking async-await

我在C#中使用HttpClient时疯狂...

我简化了我的项目,因此可以更轻松地复制我的问题.我想做的就是在后台调用HttpClient.PostAsync而不阻塞我的UI窗口(我正在使用WPF btw).

这是我的代码(将代码删到了min.):Bing仅用于此处不显示我的私人网络服务,它当然可以替换为其他所有网站.

    private async void Window_Loaded(object sender, RoutedEventArgs e)
    {
        try {
            MyTextBlock.Text = "Waiting...";

            Uri webUri = new Uri("https://www.bing.com/");
            using (HttpClient client = new HttpClient()) {
                using (HttpResponseMessage response = await client.PostAsync(webUri, new MultipartFormDataContent())) {
                    MyTextBlock.Text = await response.Content.ReadAsStringAsync();                       
                }
            }
        } catch (Exception exc) {
            MessageBox.Show(exc.ToString(), "Unhandled Exception");
        }
    }
Run Code Online (Sandbox Code Playgroud)

当我的UI正在等待异步发布请求时,它在TextBox中显示"Waiting".当异步请求返回时,它会显示结果.什么都不应该发生.

所以这里出现了问题,有时候PostAsync方法根本就不会返回......甚至会忽略Timeout.当我调试它总是有效,但当我尝试启动应用程序时,它有时会挂起.并不总是哪个不能让错误更容易找到.我尝试了多种方法来调用请求异步,但每次都是同样的问题.

我也阅读了以下博客,其中包含异步方法中的阻塞问题,但即使使用ConfigureAwait也没有区别. http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

我可以想象在HttpClient async方法中存在一个问题,锁定主线程,因此它会导致这个问题.Wenn我在ConsoleApplication中使用相同的代码一切都很好.我的客户端和目的地之间有一个代理,但这应该不是问题.

有人可以复制这个问题吗?我在.NET Framework 4.6.1中使用C#/ WPF.

Joh*_*anP 5

你不需要await client.PostAsync(webUri, i_formData)因为你在调用返回后没有对结果做任何事情,你可以直接返回Task.改变这个;

public static Task<HttpResponseMessage> BasicRequest(MultipartFormDataContent i_formData)
{
    Uri webUri = new Uri("https://www.bing.com");

    HttpClient client = new HttpClient {
        Timeout = TimeSpan.FromSeconds(1)
    };
    return client.PostAsync(webUri, i_formData);
}
Run Code Online (Sandbox Code Playgroud)

Window_Load是一个事件处理程序.你可以做到async void,这是你不必返回的唯一时间Task.通过制作它async,您可以删除所有过于复杂的代码:

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    MyTextBlock.Text = "Waiting";
    HttpResponseMessage response = await BasicRequest(new 
    MultipartFormDataContent());
    string test = await response.Content.ReadAsStringAsync();
    this.Close();
}
Run Code Online (Sandbox Code Playgroud)

  • 好的,是的,这是有道理的.以为你试图打击bing.com,他们可能会有一些节流或其他什么.您是否尝试将`Window_Load`代码包装在`try catch`中?你可能会得到一些`AggregateException` (2认同)