【问题标题】:HttpClient timeouts before the timeout specifiedHttpClient 在指定超时之前超时
【发布时间】:2014-04-18 00:16:53
【问题描述】:

我正在使用 WP8 中的 HttpClient 并执行 Post 请求。我知道通话可能需要很长时间,因为我实际上是在模拟慢速网络场景。因此,我将HttpClient.Timeout 相应地设置为 5 分钟。

但是,我在 60 秒左右出现超时。我相信超时不起作用。 我相信这个问题中提到的 WP 存在这个问题: HttpClient Portable returns 404 notfound on WP8.

他们使用了一种解决方法,但这不适用于我的场景。其实我还想等很久。

我的问题:

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

服务器收到请求,在处理请求时,客户端中止。

更新:HttpClient.PostAsyn 返回的HttpResponseMessage 是这个"{StatusCode: 404, ReasonPhrase: '', Version: 0.0, Content: System.Net.Http.StreamContent, Headers: { Content-Length: 0 }}"。正如我所说,服务器已找到并正在接收数据并进行处理。

【问题讨论】:

  • 您确定服务器没有在 60 秒后超时?
  • 是的,我确定。我实际上也在运行服务器,我看到了进展。服务器在回复客户端之前会执行一些 CPU 密集型处理。

标签: windows-phone-8 timeout dotnet-httpclient


【解决方案1】:

经过一些搜索和一些测试,我得出的结论是,问题出在 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 开头。所以我一个一个地发送字符,它们之间的延迟

这是我的学位项目,所以我不建议将它用于生产。

顺便说一句,我也尝试使用其他字符代替标题的子字符串,例如空格字符,但这会导致 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);
        }
    }

然后,实际的处理发生在不同的线程中。

欢迎评论和批评。

【讨论】:

  • 问题不仅限于 Windows Phone 8 模拟器。我在真实设备上也遇到了问题(诺基亚 Lumia 830)。我正在尝试使用 HttpClient 发送耗时超过 60 秒的 PUT 请求,但出现 404 错误。
  • 很高兴知道。 (我猜您将超时设置为高于 60 秒?)它必须在 .Net 的可移植实现中,或者也在操作系统中。谢谢分享。
  • 是的 - 我将超时设置为 10 分钟,但 404 错误无论如何都会在 60 秒时引发。我有一些冗长的同步请求需要完成。我发现没有办法将超时时间增加到 60 秒以上。
【解决方案2】:

您可能遇到了网络流的超时。你可以通过这样做来改变它,

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 上,它可能已默认减少。

【讨论】:

  • 感谢您的回答。我试过了,但不幸的是 WebRequestHandler 不适用于 WP。
  • @JB 我最初也这么认为,但是由于某种原因,MSDN 文档说是这样。 msdn.microsoft.com/en-us/library/…
  • 有 HttpClientHandler 但没有超时。
  • @jb 是的,HttpClientHandler 是默认处理程序。
猜你喜欢
  • 1970-01-01
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 2012-11-03
  • 1970-01-01
  • 2012-04-01
  • 2011-08-26
  • 1970-01-01
相关资源
最近更新 更多