HttpWebRequest随着async和await随机失败

时间:2017-09-20 12:54:39

标签: c# .net wpf asynchronous .net-4.5

我想做几个POST-Request。

我的问题是,应用程序在我Task<...> do_POST() - 事件await期间的async void bt_publishPath_Click() - 函数中随机崩溃。

我可以执行一些POST请求(一切正常),有时await将阻止,应用程序崩溃System.NullReferenceException(经过很长时间的等待)。我不明白为什么会这样,因为它第一次起作用。

这是我到目前为止的内容

我已经注释掉了每个不重要的功能。我已经测试了没有这些代码行的代码,也发生了错误。

// MainWindow
private async void bt_publishPath_Click(object sender, RoutedEventArgs e)
{
    // gr_spinner.Visibility = Visibility.Visible;

    ApiResponse res = await ApiCall.do_POST(
        "/path",
        getBasicAuthString(),
        flink.getJsonString()
    );

    // gr_spinner.Visibility = Visibility.Collapsed;
    // Globals.errorHandling(res.Statuscode, res.Parameters[0]);
}

// ApiCall static Class
public static Task<ApiResponse> do_POST(string apiPath, string auth, string json)
{
    return Task.Run(() =>
    {
        int statuscode = 0;
        HttpWebResponse response = null;
        try
        {
            // HEADER
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiBase + apiPath);
            request.Method = "POST";
            request.ContentType = "application/json";
            request.Headers.Add("Authorization", auth);

            // DATA
            byte[] data = Encoding.ASCII.GetBytes(json);
            request.ContentLength = data.Length;
            Stream requestStream = request.GetRequestStream();
            requestStream.Write(data, 0, data.Length);
            requestStream.Close();

            // SEND AND GET RESPONSE
            /*
             * It seems to be that GetResponse() isn't called correctly.
             * The Backend doesn't receive a POST-request and the reponse stays null.
             */
            response = (HttpWebResponse)request.GetResponse();
            statuscode = (int)response.StatusCode;
        }
        catch (WebException ex)
        {
            statuscode = (int)((HttpWebResponse)ex.Response).StatusCode;
        }
        return new ApiResponse(statuscode, null, new String[] { apiPath });
    });
}

其他信息

在使用async和await执行此操作之前,我尝试使用BackgroundWorker解决此问题。在这种情况下,我遇到了类似的问题:有时前一个POST的backgroundWorker仍然忙,程序无法启动新程序(死锁)。

此外,我发现了一些有趣的东西:async await Task null reference exception

  • 但在这种情况下,它是一个ASP.NET应用程序。我正在开发一个Windows桌面客户端 - 而不是服务器应用程序。所以这并没有真正的帮助。

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

在你的catch区块中,你有function removeAnswer(that) { console.log(that.parent().index()); //that.parent().remove(); }

来自MSDN

  

如果可以从Internet资源获得响应,则WebResponse实例包含来自Internet资源的错误响应;否则,null。

因此,您的问题是无响应的服务器以及错误处理中的错误 但是不要解决这个问题,查看HttpClient并编写一个新的(HttpWebResponse)ex.Response

答案 1 :(得分:1)

<强>解

非常感谢Henk Holterman。他给了我建议,使用HttpClient代替HttpWebRequest。对于像我这样有同样问题的每个人:你会得到HttpClient作为NuGet-Package。

<强> ApiCall.cs

private static HttpClient httpClient = new HttpClient();

public static async Task<HttpResponseMessage> do_POST(string apiPath, string auth, string json)
{
    HttpResponseMessage response;
    StringContent request = new StringContent(json);
    request.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", auth);
    try
    {
        response = await httpClient.PostAsync(new Uri(apiBase + apiPath), request);
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine(ex.Message);
        return null;
    }
    return response;
}

<强> MainWindow.cs

private async void bt_publishPath_Click(object sender, RoutedEventArgs e)
{
    // [...]
    HttpResponseMessage res = await ApiCall.do_POST(
        "/path",
        "admin:123456",
        "{ \"hello\" : \"world\" }"
    );
    // [...]
}