I just spent a long time breaking my teeth on why this code was 'hanging' for some urls:
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)
}
After managing to track down which of the 3000 urls was hanging, I learned that AsyncGetResponse
doesn't take any notice of HttpWebRequest.Timeout
. I've done a bit of searching which throws up suggestions of wrapping the async request in a thread with a timer. That's great for C#, but if I'm running 3000 of these through Async.Parallel |> Async.RunSynchronously
, what's the best way to handle this problem?
I've only roughly tested this, but it should have the correct behavior:
In your code, call
req.AsyncGetResponseWithTimeout()
instead ofreq.AsyncGetResponse()
.