如何并行执行两个不同结果类型的Async <>调用?

Mar*_*cze 6 f# asynchronous

我有两个异步操作,所以我有这些功能:

// Returs Async<Person>
let GetPerson =
  ...

// Returs Async<Address>
let GetAddress =
  ...
Run Code Online (Sandbox Code Playgroud)

什么是并行执行它们并获得结果的惯用方法?

我的出发点是这种方法.

let MyFunc = async {
    let! person = GetPerson()
    let! address = GetAddress()
    ...
  }
Run Code Online (Sandbox Code Playgroud)

这有效,但这会按顺序运行两个操作.

我也试过这个(基于我的C#体验).

let MyFunc = async {
    let personA = GetPerson()
    let addressA = GetAddress()
    let! person = personA
    let! address = addressA
    ...
  }
Run Code Online (Sandbox Code Playgroud)

但它不起作用,它也按顺序运行这两个操作.

大多数文档所说的是Async.Parallel与序列一起使用,但问题是两个操作的结果类型不同,所以我不能将它们放在一个序列中.

let MyFunc = async {
    let personA = GetPerson()
    let addressA = GetAddress()

    [personA; addressA]
    |> Async.Parallel
    ...
  }
Run Code Online (Sandbox Code Playgroud)

这会产生编译错误,因为这两个值具有不同的类型.(而且,使用这种语法,我怎么能得到实际结果?)

这样做的惯用方法是什么?

Tom*_*cek 8

惯用方法是Async.StartAsChild使用第二个开始计算,然后等待它们完成let!:

let MyFunc = async {
    let! personWork = GetPerson() |> Async.StartChild
    let! addressWork = GetAddress() |> Async.StartChild
    let! person = personWork
    let! address = addressWork
    // (...)
  }
Run Code Online (Sandbox Code Playgroud)

只是调用GetPerson实际上并没有启动工作 - 与在C#中创建任务的开始不同,F#工作流只是要完成的工作的描述,因此需要明确地启动它们.该Async.StartChild操作为您提供了一个工作流,可以启动工作并返回另一个可用于等待其完成的工作流.