F#异步和匿名函数

时间:2014-02-23 15:09:01

标签: asynchronous f#

我有一个使用此签名执行某些IO的方法:

member this.IsRestaurantInCatagoryAsync(restaurantName: string, restaurantAddress: string, restaurantCatagory: string) =
    async { ///long running methods }

我想在匿名函数中调用它:

this.GetRestaurants()
        |> Seq.filter(fun (name, address) -> catagoryRepository.IsRestaurantInCatagoryAsync(name, address,catagory))
        |> Seq.toList

问题是IsRestaurantInCatagoryAsync返回异步,而不是bool。我如何让Seq.Filter处理它?我应该使用let将异步转换为bool!那么我必须写一个非匿名函数来分配回报吗?

1 个答案:

答案 0 :(得分:3)

您可以使用Async.RunSynchronously同步运行操作 - 但这样做会破坏使用异步工作流以避免编写阻止代码的问题,因此这不是正确的方法!

有不同的方法可以执行此操作 - 您可以按顺序迭代所有餐馆(将逐个处理)或者您可以并行运行过滤(这将使用与.NET发现的一样多的线程池线程)。 / p>

并行版本如下所示:

let checkAll = async {
  let! all =  
    [ for r in this.GetRestaurants() -> async {
        let! include = catagoryRepository.IsRestaurantInCatagoryAsync(name, address,catagory) 
        if include then return Some(r) else return None } ]
    |> Async.Parallel
  let included = Seq.choose id all 
  printfn "%A" included }

请注意,代码全部位于async块内(因为这会使其保持异步)。它首先创建一个计算列表,返回选项None(跳过餐馆)或Some(包括餐馆),然后运行所有这些选项并使用{{过滤None值1}}。

要按顺序实现此功能,您基本上需要自己实现的Seq.choose包含在filter块中。这将是一个很好的起点(尽管它不是尾递归的):

async