我正在使用WP8中的HttpClient并执行Post请求。我知道这个电话可能需要很长时间,因为我实际上是在模拟慢速网络场景。因此,我将HttpClient.Timeout
相应地设置为5分钟。
然而,我会在60多岁时超时。我认为超时不起作用。我认为WP存在一个问题,如本问题所述:HttpClient Portable返回在WP8上找不到404。
他们使用了一种变通方法,但这不适用于我的场景。我确实想等很长时间。
我的问题:
1) 是WP8的HttpClient的错误/问题,还是我没有正确设置它?2) 你有没有想过一个仍然使用HttpClient的解决方案?
我读到HttpWebRequest可能是一个选项。然而,我认为HttpClient应该是这种"简单"场景的理想选择。
我的代码很简单:
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);
}
服务器接收到请求,在处理该请求时,客户端中止。
UPDATE:HttpClient.PostAsyn
返回的HttpResponseMessage
就是这个"{StatusCode: 404, ReasonPhrase: '', Version: 0.0, Content: System.Net.Http.StreamContent, Headers: { Content-Length: 0 }}"
。正如我所说,服务器已经找到,正在接收数据并进行处理。
经过一些搜索和测试,我得出的结论是问题出在Windows Phone本身,它有60秒的超时(与HttpClient无关),据我所知,这是无法更改的。看见http://social.msdn.microsoft.com/Forums/en-US/faf00a04-8a2e-4a64-b1c1-74c52cf685d3/httpwebrequest-60-seconds-timeout.
当我也在为服务器编程时,我会在上面提供的链接中尝试Darin Rousseau的建议,特别是发送一个OK,然后进行更多的处理。
更新:问题似乎是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连接就会超时。
因此,我的解决方案是使用Http头字符作为一种保持活动的方式。第一行Http头响应总是以HTTP/1.0
开头。所以我一个接一个地延迟发送字符<60年代。当然,如果响应准备好了,剩下的所有内容都会立即发送。这争取了一些时间,例如,如果使用每9个字符50秒的延迟,我们会得到大约450秒。
这是我的学位项目,所以我不推荐它用于生产。
顺便说一句,我还尝试使用其他字符来代替标头的子字符串,例如空格字符,但这会导致违反http协议。
这是代码的主要部分:
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);
}
}
然后,实际处理发生在另一个线程中。
欢迎评论和批评者。
可能是网络流超时了。你可以通过这样做来改变这一点,
var handler = new WebRequestHandler();
handler.ReadWriteTimeout= 5 * 60 * 1000;
var client = new HttpClient(handler);
client.Timeout = TimeSpan.FromMinutes(5);
return await client.PostAsync(serverUri, httpContent).ConfigureAwait(false);
桌面操作系统上的默认时间已经是5分钟。但是,在Windows Phone上,它可能已默认减少。