2015-08-09 23 views
7

Ich habe folgende Interface-Methode:Umschreiben von C# -Code mit Task.WhenAll in F #

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

und deren Umsetzung in C#:

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

Wenn ich versuche, es in F # neu zu schreiben:

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 |> ?? 

Ich bin mit den letzten Zeilen fest.

Wie zurück zu Task<string[]> von F # richtig?

Antwort

6

Ich musste raten, was der Typ von containerClient ist und die nächste, die ich fand, ist CloudBlobClient (die nicht getContainer: string -> Task<CloubBlobContainer> hat, aber es sollte nicht zu schwer sein, sich anzupassen). Dann könnte Ihre Funktion wie folgt aussehen:

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 

ich den Rückgabetyp geändert werden Task<string[]> statt Task<string seq> wie ich nehme an, Sie die Schnittstelle halten möchten. Andernfalls würde ich vorschlagen, die Task loszuwerden und Async in F # -only Code zu verwenden.

+0

Entschuldigung, ich vermisse es, 'containerClient.GetContainerReference' zu ​​beschreiben. Es ist eine Abstraktion über "CloudStorageAccount" von Azure SDK. Und ja, Sie haben Recht, der tatsächliche Rückgabetyp ist "Task ". War früher 'Task >' aber ich habe das geändert. – abatishchev

+0

Die Sache, die ich nicht kannte, ist 'Async.Parallel' und komplett vergessen' return! '. – abatishchev

4

Funktioniert das?

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 

Ich hatte einige Annahmen über containerClient usw. zu machen, damit ich nicht in der Lage gewesen, dies zu testen, aber zumindest kompiliert.

+0

Hallo Markus, danke für deine Antwort! Entschuldigung, ich vermisse es zu beschreiben, was 'containerClient.GetContainerReference()' ist. Warum brauchst du hier eine zusätzliche Funktion "aMap"? – abatishchev

+0

Um 'Async ' in 'Async ' umzuwandeln. –

+0

Ich sehe. Also, wenn ich 'Aufgabe ' zurückgeben kann, dann brauche ich es nicht? – abatishchev