我有一个使用此签名执行某些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!那么我必须写一个非匿名函数来分配回报吗?
答案 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