Asynchronous function calls in Parallel

2019-08-21 10:32发布

Following version is calling all functions synchronously,

I'm looking to find out how to call asynchronous functions in parallel and return all results and errors to the caller.

Request

let requestAsync (url: string) : Async<Result<string, Error>> =
    async {
        Console.WriteLine ("Simulating request " + url)
        try
            do! Async.Sleep(1000)
            return Ok (url + ": body...")
        with :? WebException as e ->
            return Error {code = 500; message = "Internal Server Error";}
    }

Test

[<TestMethod>]
member this.TestrequestAsync() =
    let urls = [|
        "http://www.example.com/1";
        "http://www.example.com/2";
        "http://www.example.com/3";
        "http://www.example.com/4";
        "http://www.example.com/5";
        "http://www.example.com/6";
        "http://www.example.com/7";
        "http://www.example.com/8";
        "http://www.example.com/9";
        "http://www.example.com/10";
    |]

    urls
    |> Array.map (fun url -> requestAsync url |> Async.RunSynchronously) // Async.Parallel some mismatch

    // Iterate results

Ideally to be able to match Ok and Error results while iterating through results

Edit based on the answer.

let result =
    urls
    |> Seq.map Entity.requestDetailAsync2
    |> Async.Parallel
    |> Async.RunSynchronously


result
|> Array.iter Console.WriteLine // match x with Ok and Error?

Attempt

result |> Array.iter (fun data -> match data with
                                      | Ok result -> Console.WriteLine(result)
                                      | Error error -> Console.WriteLine(error) )

Iteration using For in

for r in result do
    match r with
    | Ok re -> Console.WriteLine(re)
    | Error error -> Console.WriteLine(error)

1条回答
爷的心禁止访问
2楼-- · 2019-08-21 11:08

You can use Async.Parallel to run many async operations in parallel:

let results =
  urls
  |> Seq.map requestAsync   // seq<Async<'T>>
  |> Async.Parallel         // async<T' []>
  |> Async.RunSynchronously // T' []

Here's a very similar example on MSDN.

There may be an issue with your requestAsync function return type, or a missing type definition in your example. Here's what I used to verify the solution:

type RequestError = {
  code : int
  message : string
}

let requestAsync (url: string) =
    async {
        Console.WriteLine ("Simulating request " + url)
        try
            do! Async.Sleep(1000)
            return Ok (url + ": body...")
        with :? WebException as e ->
            return Error {code = 500; message = "Internal Server Error";}
    }
查看更多
登录 后发表回答