【发布时间】:2019-03-29 13:45:58
【问题描述】:
所以我目前有一个seq<System.Threading.Tasks.Task<Restaurant>> 类型的序列,我想把它变成seq<Restaurant> 类型的序列。
我目前正在使用 TaskBuilder.fs 库,根据我的研究,我需要使用任一 let!或者做!对于这种情况,但他们需要task {},当与 Seq.map 一起使用时,会返回相同的任务类型。
let joinWithReviews (r : Restaurant) =
task {
let! reviewResult = Reviews.Database.getByLocationId cnf.connectionString r.Restaurant_Id
match reviewResult with
| Ok reviewResult ->
let restaurant = { r with Reviews = (List.ofSeq reviewResult)}
return restaurant
| Error ex ->
return raise ex
}
let indexAction (ctx : HttpContext) =
task {
let (cnf:Config) = Controller.getConfig ctx
let! result = Restaurants.Database.getAll cnf.connectionString
match result with
| Ok result ->
let restaurantWithReviews = (Seq.map joinWithReviews result)
return index ctx (List.ofSeq restaurantWithReviews)
| Error ex ->
return raise ex
}
所以我的结果是 Seq<Restaurant> 类型,我需要为每家餐厅添加评论,所以我使用 Seq.map 来获取我无法使用的 seq<System.Threading.Tasks.Task<Restaurant>> 类型的 restaurantWithReviews。
【问题讨论】:
-
您是否尝试并行执行某些处理?
-
我不需要并行处理它,但我的数据库调用属于 Task 类型,我使用的框架需要与我的 IndexAction 相同。
-
要将
seq<Task<TResult>>转换为seq<TResult>,最简单的方法是简单的|> Seq.map (fun task -> task.Result)。 MSDN docs 表示访问 Task 的Result属性将阻塞线程,直到结果可用,请注意这将是顺序的,而不是并行的。但这绝对是满足您需要的最简单、最简单的方法。 -
谢谢!这足以满足我的需求。
-
如果我想按顺序运行
Seq.map而不必通过调用task.Result来阻塞线程怎么办?
标签: f# task saturn-framework