2015-08-09 18 views
7

tôi có phương pháp giao diện sau:Viết lại C# mã sử dụng Task.WhenAll trong F #

Task<string[]> GetBlobsFromContainer(string containerName); 

và thực hiện nó trong C#:

var container = await _containerClient.GetContainer(containerName); 
var tasks = container.ListBlobs() 
        .Cast<CloudBlockBlob>() 
        .Select(b => b.DownloadTextAsync()); 
return await Task.WhenAll(tasks); 

Khi tôi cố gắng viết lại nó trong 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 |> ?? 

Tôi đang mắc kẹt với các dòng cuối cùng.

Cách quay lại Task<string[]> từ F # đúng cách?

Trả lời

6

Tôi phải đoán loại containerClient là gì và gần nhất tôi thấy là CloudBlobClient (không có getContainer: string -> Task<CloubBlobContainer> nhưng không quá khó để thích ứng). Sau đó, chức năng của bạn có thể trông giống như sau:

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 

Tôi đã thay đổi kiểu trả về là Task<string[]> thay vì Task<string seq> như tôi giả sử bạn muốn giữ lại giao diện. Nếu không, tôi khuyên bạn nên loại bỏ Task và sử dụng Async trong mã F # -only.

+0

Xin lỗi, bỏ lỡ mô tả 'containerClient.GetContainerReference'. Đó là một sự trừu tượng trên đầu trang của 'CloudStorageAccount' từ Azure SDK. Và vâng, bạn nói đúng, kiểu trả về thực tế là 'Task '. Đã từng là 'Tác vụ >' nhưng tôi đã thay đổi điều đó. – abatishchev

+0

Điều tôi không biết là 'Async.Parallel' và hoàn toàn quên về 'return!'. – abatishchev

4

Điều này có hiệu quả không?

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 

Tôi phải đưa ra một số giả định về containerClient v.v. vì vậy tôi chưa thể thử nghiệm điều này, nhưng ít nhất nó biên dịch.

+0

Xin chào Mark, cảm ơn bạn đã trả lời! Xin lỗi, bỏ lỡ để mô tả những gì 'containerClient.GetContainerReference()' là. Tại sao bạn cần ở đây một hàm bổ sung 'aMap'? – abatishchev

+0

Để chuyển đổi 'Async 'thành' Async '. –

+0

Tôi hiểu. Vì vậy, nếu tôi có thể trả lại 'Task ' thì tôi không cần nó? – abatishchev