问题
I would like to do serveral POST-Request.
My problem is that the Application crashes randomly in the Task<...> do_POST()
-Function during await
in my async void bt_publishPath_Click()
-Event.
I can do some POST-Requests (everything's working fine) and sometime the await
will block and the app crashes with a System.NullReferenceException
(after a long time of waiting). I don't understand why this is happing because the first times it is working.
Here is what I got so far:
I have commented out every unimportant functionality. I have tested my code without these lines of code and the error occures, too.
// 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 });
});
}
Additional information:
Before doing this with async and await I tried to solve this issue by using a BackgroundWorker. In this case I had a similar problem: Sometimes the backgroundWorker of the previous POST was still busy and the program wasn't able to start a new one (deadlock).
Furthermore I have found something interesting: async await Task null reference exception
- But in this case it is a ASP.NET-Application. I am developing a Windows-Desktop client - not a server application. So this doesn't really help.
Thank you for your help!
回答1:
In your catch block you have (HttpWebResponse)ex.Response
.
From MSDN:
If a response is available from the Internet resource, a WebResponse instance that contains the error response from an Internet resource; otherwise, null.
So your problem is a non-responsive server and an error in your error handling.
But don't fix this, look up the HttpClient and write a new async Task<> DoPost(...)
.
回答2:
SOLUTION
Big thanks to Henk Holterman. He gave me advice to use HttpClient
instead of HttpWebRequest
. For everyone having the same problem like me: You will get HttpClient as a 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\" }"
);
// [...]
}
来源:https://stackoverflow.com/questions/46322673/httpwebrequest-randomly-fails-with-async-and-await