簡體   English   中英

F# 異步和匿名函數

[英]F# async and anonymous functions

我有一個用這個簽名做一些 IO 的方法:

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

我想像這樣在匿名函數中調用它:

this.GetRestaurants()
        |> Seq.filter(fun (name, address) -> categoryRepository.IsRestaurantInCategoryAsync(name, address, category))
        |> Seq.toList

問題是 IsRestaurantInCategoryAsync 返回async<bool> ,而不是bool 我如何讓Seq.Filter處理它?

我應該使用 let 將async<bool>轉換為bool嗎? 那么我必須編寫一個非匿名函數來分配回報嗎?

您可以使用Async.RunSynchronously同步運行操作 - 但這會破壞使用異步工作流來避免編寫阻塞代碼的意義,因此這不是正確的方法!

有不同的方法可以做到這一點 - 您可以按順序遍歷所有餐廳(將一個一個處理),或者您可以並行運行過濾(它將使用 .NET 認為好的線程池線程)。

並行版本如下所示:

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 (包括餐廳)的選項,然后運行所有選項並使用Seq.choose過濾None值。

要按順序實現這一點,您基本上需要自己的過濾器實現,該filter包含在async塊中。 這將是一個很好的起點(盡管它不是尾遞歸的):

let rec filterAsync f items = async {
  match items with
  | [] -> return []
  | x::xs -> 
      let! included = f x
      let! rest = filterAsync f xs
      return (if included then x::rest else rest) }

使用FSharp.Control.AsyncSeq

this.GetRestaurants()
        |> AsyncSeq.filterAsync categoryRepository.IsRestaurantInCategoryAsync name address category
        |> AsyncSeq.toListAsync

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM