简体   繁体   English

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

[英]C# HttpClient - PostAsync doesn't return (even with ConfigureAwait)

I am running crazy with using the HttpClient in C#... 我在C#中使用HttpClient感到疯狂...

I simplified my project so my problem can be replicated easier. 我简化了项目,因此可以轻松复制我的问题。 All i want to do is calling HttpClient.PostAsync in the Background without blocking my UI Window (I am using WPF btw). 我要做的就是在后台调用HttpClient.PostAsync而不阻塞我的UI窗口(我正在使用WPF btw)。

Here is my code (slimed the code to the min.): Bing is only used here to not show my private webservice it can be replaced with every other website of course. 这是我的代码(将代码限制到最低限度。):必应仅在这里用于不显示我的私人Web服务,当然可以将其替换为其他所有网站。

    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");
        }
    }

While my UI is waiting for the async post request it shows "Waiting" in a TextBox. 当我的UI等待异步发布请求时,它在TextBox中显示“正在等待”。 And when the Async Request returns it shows the result. 当异步请求返回时,它会显示结果。 Nothing more should happen. 什么也不会发生。

So here the Problem occurs, sometimes the PostAsync Method simply doesn't return... Even the Timeout is ignored. 因此,这里出现问题,有时PostAsync方法根本不返回...即使超时也被忽略。 When I am debugging it always works but when I try the start the application it somettimes hangs. 当我调试时,它总是可以工作,但是当我尝试启动应用程序时,它有时会挂起。 Not always which is not making find the error easier. 并非总是如此,这并不会使发现错误变得容易。 I tried many ways with calling the request async but every time the same issue. 我尝试了多种方法来异步调用请求,但是每次都遇到相同的问题。

I also read following blog with the blocking issue in async methods but even with ConfigureAwait no differnce. 我还阅读了以下博客,其中涉及异步方法中的阻塞问题,但即使与ConfigureAwait也没有区别。 http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

I just can imagine that there is a problem within the HttpClient async method locking the main thread, so it cause this problem. 我只是可以想象在锁定主线程的HttpClient异步方法中存在问题,因此会导致此问题。 Wenn i use the same code in a ConsoleApplication everything is fine. 温恩我在ConsoleApplication中使用相同的代码,一切都很好。 There is a proxy between my client and the destination but that shouldn't be a problem at all. 我的客户与目的地之间有一个代理,但这根本不是问题。

Can someone replicate this problem? 有人可以复制这个问题吗? I am using C#/WPF with .NET Framework 4.6.1. 我在C#/ WPF和.NET Framework 4.6.1中使用。

You don't need to await client.PostAsync(webUri, i_formData) because you don't do anything with the result after the call returns, you can just return the Task . 您不需要await client.PostAsync(webUri, i_formData)因为调用返回后您对结果不执行任何操作,只需返回Task Change to this; 更改为此;

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);
}

Your Window_Load is an event handler. 您的Window_Load是事件处理程序。 You can make it async void , which is the only time you don't have to return Task . 您可以使它async void ,这是您不必返回Task的唯一时间。 By making it async , you can remove all the over complicated code: 通过使其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();
}

First at all thanks for your help, the problem seems to be solved now. 首先,完全感谢您的帮助,该问题现在似乎已解决。

I had to do 3 things to get this work: 我必须做三件事才能完成这项工作:

  1. Get a instance of HttpClient of use it the whole application life time, so no using anymore for HttpClient. 获取在整个应用程序生命周期中都使用它的HttpClient实例,因此不再对HttpClient使用。

  2. Don't call PostAsync in the Window_Loaded Event, it seems to be to early sometimes. 不要在Window_Loaded事件中调用PostAsync,这似乎要早一些。 (I still don't get why...) (我仍然不明白为什么...)

  3. Don't use ConfigureAwait(false) 不要使用ConfigureAwait(false)

The code now looks something like this: 现在的代码如下所示:

HttpClient client = new HttpClient();

private async void MyButton_Click(object sender, RoutedEventArgs e)
{
    try {
        MyTextBlock.Text = "Waiting...";
        Uri webUri = new Uri("https://www.bing.com/");
        using (HttpResponseMessage response = await client.PostAsync(webUri, new ipartFormDataContent())) {
            MyTextBlock.Text = await response.Content.ReadAsStringAsync();
        }
    } catch (Exception exc) {
        MessageBox.Show(exc.ToString(), "Unhandled Exception");
    }
}

And to get this at start up done i had to make a really bad piece of good. 为了在启动时做到这一点,我不得不做出一件非常糟糕的事情。 But it works finally: 但它最终可以工作:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    DispatcherTimer startupTimer = new DispatcherTimer();
    startupTimer.Tick += new EventHandler((o, a) => {
        MyFunction();
        startupTimer.Stop();
    });
    startupTimer.Interval = TimeSpan.FromSeconds(1);
    startupTimer.Start();
}

When someone can replicate these behavior or can explain why these was happening, please comment it here :) 当有人可以复制这些行为或可以解释为什么发生这种情况时,请在此处进行评论:)


Update 更新资料

Issue still occurs but it seems to be only there when the client is using some kind of proxy! 问题仍然存在,但似乎仅在客户端使用某种代理时才存在!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM