HttpClient 在指定超时之前超时 [英] HttpClient timeouts before the timeout specified
问题描述
我正在使用 WP8 的 HttpClient 并执行 Post 请求.我知道通话可能需要很长时间,因为我实际上是在模拟慢速网络场景.因此,我将 HttpClient.Timeout
相应地设置为 5 分钟.
I'm using HttpClient from WP8 and do a Post request. I know the call may take long time as I'm actually simulating slow network scenarios. Therefore I set the HttpClient.Timeout
accordingly to 5 minutes.
但是,我在 60 秒左右收到超时.我相信超时不起作用.我相信 WP 存在这个问题,如本问题所述:HttpClient Portable 返回 404 notfound on WP8.
However, I get a Timeout at around 60s. I believe the Timeout is not working. I believe there is an issue with this for WP as stated in this question: HttpClient Portable returns 404 notfound on WP8.
他们使用了一种解决方法,但这不适用于我的场景.其实我很想等很久.
They use a workaround but that does not applies to my scenario. I do actually want to wait for long time.
我的问题:
1) 这是 WP8 的 HttpClient 的错误/问题还是我没有正确设置?2)您是否想到仍然使用HttpClient的解决方法?
1) Is it a bug/issue of HttpClient for WP8 or I'm not setting it properly? 2) Do you think of a workaround still using HttpClient?
我读过可能 HttpWebRequest 是一个选项.但是,我相信 HttpClient 应该是这种简单"场景的理想选择.
I've read that maybe HttpWebRequest is an option. However, I believe HttpClient should be ideal for this 'simple' scenario.
我的代码很简单:
private static async Task<HttpResponseMessage> PostAsync(Uri serverUri, HttpContent httpContent)
{
var client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(5);
return await client.PostAsync(serverUri, httpContent).ConfigureAwait(false);
}
服务器收到请求并在处理它时,客户端中止.
The server receives the request and while is processing it, the client aborts.
更新:HttpClient.PostAsyn
返回的 HttpResponseMessage
是这个 "{StatusCode: 404, ReasonPhrase: '', Version: 0.0, Content: System.Net.Http.StreamContent,标题:{ 内容长度:0 }}"
.正如我所说,服务器已找到并正在接收数据并对其进行处理.
UPDATE: The HttpResponseMessage
returned by HttpClient.PostAsyn
is this "{StatusCode: 404, ReasonPhrase: '', Version: 0.0, Content: System.Net.Http.StreamContent, Headers: { Content-Length: 0 }}"
. As I said, the server is found and is receiving the data and processing it.
推荐答案
经过一些搜索和一些测试,我得出的结论是,问题出在 Windows Phone 本身,并且它有 60 秒的超时时间(与 HttpClient 无关)),据我所知,这不能改变.请参阅 http://social.msdn.microsoft.com/Forums/en-US/faf00a04-8a2e-4a64-b1c1-74c52cf685d3/httpwebrequest-60-seconds-timeout.
After some search and some tests I've came to the conclusion that the problem is Windows Phone itself and that it has a 60 seconds timeout (irrespective of the HttpClient) and that cannot be changed to my knowledge. See http://social.msdn.microsoft.com/Forums/en-US/faf00a04-8a2e-4a64-b1c1-74c52cf685d3/httpwebrequest-60-seconds-timeout.
因为我也在对服务器进行编程,所以我将尝试上面提供的链接中 Darin Rousseau 的建议,特别是发送一个 OK 然后做一些更多的处理.
As I'm programming the server as well, I will try the advice by Darin Rousseau in the link provided above, specifically to send an OK and then do some more processing.
更新:问题似乎是此处所述的 Windows Phone 模拟器:http://social.msdn.microsoft.com/forums/wpapps/en-us/6c114ae9-4dc1-4e1f-afb2-a6b9004bf0c6/httpclient-doesnt-work-on-windows-phone?forum=wpdevelop.根据我的经验,如果 60 秒内没有听到任何消息,tcp 连接就会超时.
UPDATE: The problem seems to be the Windows Phone emulator as stated here: http://social.msdn.microsoft.com/forums/wpapps/en-us/6c114ae9-4dc1-4e1f-afb2-a6b9004bf0c6/httpclient-doesnt-work-on-windows-phone?forum=wpdevelop. In my experience the tcp connection times-out if it doesn't hear anything for 60s.
因此我的解决方案是使用 Http 标头字符作为保持活动的方式.第一行 Http 头响应总是以 HTTP/1.0
开头.所以我一个一个发送字符,它们之间的延迟 <60 秒.当然,如果响应准备好,剩下的所有内容都会立即发送.这会花费一些时间,例如,如果使用每 9 个字符 50 秒的延迟,我们会得到大约 450 秒.
Therefore my solution is to use the Http header characters as a way of keep alive. The first line Http header response always starts with HTTP/1.0
. So I send the characters one by one with a delay <60s between them. Of course, if the response gets ready, everything that is left is sent right away. This buys some time, for instance if using a delay of 50s per 9 character we get about 450s.
这是我的学位项目,所以我不建议将其用于生产.
This is a project for my degree so I wouldn't recommend it for production.
顺便说一句,我还尝试使用其他字符代替标头的子字符串,例如空格字符,但这会导致违反 http 协议.
By the way, I also tried with other characters instead the sub string of the header, for instance space character, but that results in a http protocol violation.
这是代码的主要部分:
private const string Header1 = @"HTTP/1.0 ";
private int _keepAliveCounter = 0;
private readonly object _sendingLock = new object();
private bool _keepAliveDone = true;
private void StartKeepAlive()
{
Task.Run(() => KeepAlive());
}
/// <summary>
/// Keeps the connection alive sending the first characters of the http response with an interval.
/// This is a hack for Windows Phone 8 that need reponses within 60s interval.
/// </summary>
private void KeepAlive()
{
try
{
_keepAliveDone = false;
_keepAliveCounter = 0;
while (!_keepAliveDone && _keepAliveCounter < Header1.Length)
{
Task.Delay(TimeSpan.FromSeconds(50)).Wait();
lock (_sendingLock)
{
if (!_keepAliveDone)
{
var sw = new StreamWriter(OutputStream);
sw.Write(Header1[_keepAliveCounter]);
Console.Out.WriteLine("Wrote keep alive char '{0}'", Header1[_keepAliveCounter]);
_keepAliveCounter++;
sw.Flush();
}
}
}
_keepAliveCounter = 0;
_keepAliveDone = true;
}
catch (Exception e)
{
// log the exception
Console.Out.WriteLine("Error while sending keepalive: " + e.Message);
}
}
然后,实际处理发生在不同的线程中.
Then, the actual processing happens in a different thread.
感谢评论和批评.
这篇关于HttpClient 在指定超时之前超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!