我目前有一个类型为seq<System.Threading.Tasks.Task<Restaurant>>
的序列,我想把它转换成类型为seq<Restaurant>
的序列。
我目前正在使用TaskBuilder.fs库,从我的研究来看,我需要使用let!或do!来处理这种情况,但它们需要task {}
,而当与Seq.map一起使用时会带回相同的Task类型。
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
获取restaurantWithReviews
,它的类型是seq<System.Threading.Tasks.Task<Restaurant>>
,但我将无法使用它。
seq<Task<TResult>>
转换成seq<TResult>
,最简单的方法是使用简单的|> Seq.map (fun task -> task.Result)
。根据MSDN文档显示,访问任务的Result
属性将会阻止线程,直到结果可用,并且请注意这将是顺序执行而不是并行处理。但这绝对是你需要做的最简单、最直接的方式。 - rmunnSeq.map
而不必通过调用task.Result
阻塞线程,该怎么办? - David Spiess