2016-07-23 9 views
2

Ich mache viele asynchrone Web-Anfragen und Async.Parallel verwenden. Etwas wie:F # Weiter auf Async.Catch

Einige Anfrage kann Ausnahmen auslösen, ich möchte sie protokollieren und mit dem Rest der URLs fortfahren. Ich habe die Async.Catch Funktion gefunden, aber dies stoppt die Berechnung, wenn die erste Ausnahme ausgelöst wird. Ich wissen Ich kann einen Ausdruck try...with innerhalb der Async-Ausdruck verwenden, um die gesamte Liste zu berechnen, aber ich denke, das bedeutet, eine Protokollfunktion an meine downloadAsync Funktion übergeben seinen Typ zu übergeben. Gibt es eine andere Möglichkeit, die Ausnahmen zu erfassen, sie zu protokollieren und mit den restlichen URLs fortzufahren?

+1

Ihre Frage ist mir unklar ... Was wollen Sie jenseits 'xs |> Seq.map (Spaß u -> Async.Catch <| downloadAsync u.Url) |> Async.Parallel'? – ildjarn

+0

Entschuldigung, wenn schlecht Englisch in meiner Frage :(Der Code in Ihrem Kommentar funktioniert für mich! Danke – Nicolocodev

Antwort

4

Der ‚Trick‘ ist den Fang in die Karte so zu bewegen, dass Fang als auch parallelisiert:

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 
*) 

Hier wickelte ich den Download in einer anderen async die Uri Bau Ausnahme zu erfassen.

+0

yay! Danke! – Nicolocodev