2016-07-23 2 views
2

Я делаю много асинхронных веб-запросов и используя Async.Parallel. Что-то вроде:F # Продолжить на Async.Catch

xs       
|> Seq.map (fun u -> downloadAsync u.Url) 
|> Async.Parallel 
|> Async.Catch 

Некоторые запросы могут исключать исключения, я хочу их зарегистрировать и продолжить с остальными адресами. Я нашел функцию Async.Catch, но это остановит вычисление, когда вызывается первое исключение. I know Я могу использовать выражение try...with в выражении async, чтобы вычислить весь список, но, я думаю, это подразумевает передачу функции журнала моей функции downloadAsync, изменяющей его тип. Есть ли другой способ поймать исключения, зарегистрировать их и продолжить с остальными URL-адресами?

+1

Ваш вопрос непонятен мне ... Что вы хотите за пределами 'xs |> Seq.map (fun u -> Async.Catch <| downloadAsync u.Url) |> Async.Parallel'? – ildjarn

+0

извините, если плохой английский в моем вопросе :(Код в вашем комментарии работает для меня! Спасибо – Nicolocodev

ответ

4

Основная хитрость заключается в перемещении улова в карту таким образом, чтобы ловить распараллеливаются а:

open System 
open System.IO 
open System.Net 

type T = { Url : string } 

let xs = [ 
    { Url = "http://microsoft.com" } 
    { Url = "thisDoesNotExists" } // throws when constructing Uri, before downloading 
    { Url = "https://thisDotNotExist.Either" } 
    { Url = "http://google.com" } 
] 

let isAllowedInFileName c = 
    not <| Seq.contains c (Path.GetInvalidFileNameChars()) 

let downloadAsync url = 
    async { 
     use client = new WebClient() 
     let fn = 
      [| 
       __SOURCE_DIRECTORY__ 
       url |> Seq.filter isAllowedInFileName |> String.Concat 
      |] 
      |> Path.Combine 
     printfn "Downloading %s to %s" url fn 
     return! client.AsyncDownloadFile(Uri(url), fn) 
    } 

xs 
|> Seq.map (fun u -> downloadAsync u.Url |> Async.Catch) 
|> Async.Parallel 
|> Async.RunSynchronously 
|> Seq.iter (function 
    | Choice1Of2() -> printfn "Succeeded" 
    | Choice2Of2 exn -> printfn "Failed with %s" exn.Message) 

(* 
Downloading http://microsoft.com to httpmicrosoft.com 
Downloading thisDoesNotExists to thisDoesNotExists 
Downloading http://google.com to httpgoogle.com 
Downloading https://thisDotNotExist.Either to httpsthisDotNotExist.Either 
Succeeded 
Failed with Invalid URI: The format of the URI could not be determined. 
Failed with The remote name could not be resolved: 'thisdotnotexist.either' 
Succeeded 
*) 

Здесь я завернутая загрузку в другую async захватить исключение Uri строительства.

+0

yay! Спасибо! – Nicolocodev

Смежные вопросы