在 F# 中使用 Task.WhenAll 重写 C# 代码
Rewriting C# code using Task.WhenAll in F#
我有以下接口方法:
Task<string[]> GetBlobsFromContainer(string containerName);
及其在 C# 中的实现:
var container = await _containerClient.GetContainer(containerName);
var tasks = container.ListBlobs()
.Cast<CloudBlockBlob>()
.Select(b => b.DownloadTextAsync());
return await Task.WhenAll(tasks);
当我尝试用 F# 重写它时:
member this.GetBlobsFromContainer(containerName : string) : Task<string[]> =
let task = async {
let! container = containerClient.GetContainer(containerName) |> Async.AwaitTask
return container.ListBlobs()
|> Seq.cast<CloudBlockBlob>
|> Seq.map (fun b -> b.DownloadTextAsync())
|> ??
}
task |> ??
我卡在最后几行了。
如何正确地从 F# return 到 Task<string[]>
?
我不得不猜测 containerClient
的类型是什么,我找到的最接近的是 CloudBlobClient
(它没有 getContainer: string -> Task<CloubBlobContainer>
但应该不会太难适应).然后,您的函数可能如下所示:
open System
open System.Threading.Tasks
open Microsoft.WindowsAzure.Storage.Blob
open Microsoft.WindowsAzure.Storage
let containerClient : CloudBlobClient = null
let GetBlobsFromContainer(containerName : string) : Task<string[]> =
async {
let container = containerClient.GetContainerReference(containerName)
return! container.ListBlobs()
|> Seq.cast<CloudBlockBlob>
|> Seq.map (fun b -> b.DownloadTextAsync() |> Async.AwaitTask)
|> Async.Parallel
} |> Async.StartAsTask
我将 return 类型更改为 Task<string[]>
而不是 Task<string seq>
因为我想你想保留界面。否则,我建议去掉 Task
并在 F#-only 代码中使用 Async
。
这行得通吗?
member this.GetBlobsFromContainer(containerName : string) : Task<string seq> =
let aMap f x = async {
let! a = x
return f a }
let task = async {
let! container = containerClient.GetContainer(containerName) |> Async.AwaitTask
return! container.ListBlobs()
|> Seq.cast<CloudBlockBlob>
|> Seq.map (fun b -> b.DownloadTextAsync() |> Async.AwaitTask)
|> Async.Parallel
|> aMap Array.toSeq
}
task |> Async.StartAsTask
我不得不对 containerClient
等做出一些假设,所以我无法对此进行测试,但至少它可以编译。
我有以下接口方法:
Task<string[]> GetBlobsFromContainer(string containerName);
及其在 C# 中的实现:
var container = await _containerClient.GetContainer(containerName);
var tasks = container.ListBlobs()
.Cast<CloudBlockBlob>()
.Select(b => b.DownloadTextAsync());
return await Task.WhenAll(tasks);
当我尝试用 F# 重写它时:
member this.GetBlobsFromContainer(containerName : string) : Task<string[]> =
let task = async {
let! container = containerClient.GetContainer(containerName) |> Async.AwaitTask
return container.ListBlobs()
|> Seq.cast<CloudBlockBlob>
|> Seq.map (fun b -> b.DownloadTextAsync())
|> ??
}
task |> ??
我卡在最后几行了。
如何正确地从 F# return 到 Task<string[]>
?
我不得不猜测 containerClient
的类型是什么,我找到的最接近的是 CloudBlobClient
(它没有 getContainer: string -> Task<CloubBlobContainer>
但应该不会太难适应).然后,您的函数可能如下所示:
open System
open System.Threading.Tasks
open Microsoft.WindowsAzure.Storage.Blob
open Microsoft.WindowsAzure.Storage
let containerClient : CloudBlobClient = null
let GetBlobsFromContainer(containerName : string) : Task<string[]> =
async {
let container = containerClient.GetContainerReference(containerName)
return! container.ListBlobs()
|> Seq.cast<CloudBlockBlob>
|> Seq.map (fun b -> b.DownloadTextAsync() |> Async.AwaitTask)
|> Async.Parallel
} |> Async.StartAsTask
我将 return 类型更改为 Task<string[]>
而不是 Task<string seq>
因为我想你想保留界面。否则,我建议去掉 Task
并在 F#-only 代码中使用 Async
。
这行得通吗?
member this.GetBlobsFromContainer(containerName : string) : Task<string seq> =
let aMap f x = async {
let! a = x
return f a }
let task = async {
let! container = containerClient.GetContainer(containerName) |> Async.AwaitTask
return! container.ListBlobs()
|> Seq.cast<CloudBlockBlob>
|> Seq.map (fun b -> b.DownloadTextAsync() |> Async.AwaitTask)
|> Async.Parallel
|> aMap Array.toSeq
}
task |> Async.StartAsTask
我不得不对 containerClient
等做出一些假设,所以我无法对此进行测试,但至少它可以编译。