【问题标题】:How to handle HttpWebRequest timeout in F# Async.Parallel如何在 F# Async.Parallel 中处理 HttpWebRequest 超时
【发布时间】:2011-04-19 08:02:01
【问题描述】:

我刚刚花了很长时间才弄清楚为什么这段代码对于某些网址“挂起”:

let getImage (imageUrl:string) =
    async {
        try
            let req = WebRequest.Create(imageUrl) :?> HttpWebRequest
            req.UserAgent <- "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)";
            req.Method <- "GET";
            req.AllowAutoRedirect <- true;
            req.MaximumAutomaticRedirections <- 4;
            req.Timeout <- 3000; //HAHAHA, nice try!
            let! response1 = req.AsyncGetResponse()
            let response = response1 :?> HttpWebResponse
            use stream = response.GetResponseStream()
            let ms = new MemoryStream()
            let bytesRead = ref 1
            let buffer = Array.create 0x1000 0uy
            while !bytesRead > 0 do
                bytesRead := stream.Read(buffer, 0, buffer.Length)
                ms.Write(buffer, 0, !bytesRead)
            return SuccessfulDownload(imageUrl, ms.ToArray())

        with
            ex -> return FailedDownload(imageUrl, ex.Message)
    }

在设法追踪 3000 个 URL 中的哪个被挂起后,我了解到 AsyncGetResponse 没有注意到 HttpWebRequest.Timeout。我做了一些搜索,提出了将异步请求包装在带有计时器的线程中的建议。这对 C# 来说很棒,但如果我通过 Async.Parallel |&gt; Async.RunSynchronously 运行其中的 3000 个,那么处理这个问题的最佳方法是什么?

【问题讨论】:

  • 您应该只使用stream.CopyTo ms 而不是使用bufferbytesRead 进行所有手动复制。
  • @ildjarn,感谢您的信息,我不得不承认这是来自here的直接复制粘贴

标签: asynchronous f# httpwebrequest


【解决方案1】:

我只是粗略地测试了一下,但它应该有正确的行为:

type System.Net.WebRequest with
  member req.AsyncGetResponseWithTimeout () =
    let impl = async {
      let iar = req.BeginGetResponse (null, null)
      let! success = Async.AwaitIAsyncResult (iar, req.Timeout)
      return if success then req.EndGetResponse iar
             else req.Abort ()
                  raise (System.Net.WebException "The operation has timed out") }
    Async.TryCancelled (impl, fun _ -> req.Abort ())

在您的代码中,调用 req.AsyncGetResponseWithTimeout() 而不是 req.AsyncGetResponse()

【讨论】:

  • 嗯,我说得太早了。它适用于少数人,但我现在有很多超时。 WebRequest 是否有可能在内部管理并发连接的数量,现在我正在排队请求超时?我会继续挖掘......
  • @Benjol :是的,我记得,默认情况下,它内部限制为两个同时连接。我似乎记得虽然解决这个问题很简单。我将查看我的一些旧 C# 代码,尝试记住如何操作。
  • 花了一些时间整理这段代码。我目前的理解是所有这些 WebRequest 都是“立即”启动的,所以为了让它工作,我必须将超时设置为下载 all 所需的时间。没有时间进一步调查。
  • @Benjol :这意味着您使用 getImage 的方式存在问题,而不是getImage 本身(或AsyncGetResponseWithTimeout)的问题。
猜你喜欢
  • 2015-01-28
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-01
  • 1970-01-01
相关资源
最近更新 更多