2015-08-09 16 views
7

Ho la seguente metodo di interfaccia:riscrivere il codice C# utilizzando Task.WhenAll in F #

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

e la sua implementazione in C#:

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

Quando provo a riscriverlo in 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 |> ?? 

Sono bloccato con le ultime righe.

Come tornare a Task<string[]> da F # correttamente?

risposta

6

Ho dovuto indovinare quale sia il tipo di containerClient e il più vicino che ho trovato è CloudBlobClient (che non ha getContainer: string -> Task<CloubBlobContainer> ma non dovrebbe essere troppo difficile adattarlo). Quindi, la funzione potrebbe essere simile come segue:

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 

ho cambiato il tipo di ritorno per essere Task<string[]> anziché Task<string seq> come suppongo che si desidera mantenere l'interfaccia. Altrimenti, suggerirei di eliminare lo Task e utilizzare Async nel codice F # -only.

+0

Scusa, mancare di descrivere 'containerClient.GetContainerReference'. È un'astrazione in cima a "CloudStorageAccount" di Azure SDK. E sì, hai ragione, il tipo di ritorno effettivo è 'Compito '. Usato per essere 'Compito >' ma l'ho cambiato. – abatishchev

+0

La cosa che non sapevo è 'Async.Parallel' e mi sono completamente dimenticato di' return! '. – abatishchev

4

Funzionerà?

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 

ho dovuto fare alcune ipotesi circa containerClient ecc così non ho potuto testare questo, ma almeno si compila.

+0

Ciao Mark, grazie per la tua risposta! Scusa, mancare di descrivere cosa 'containerClient.GetContainerReference()' è. Perché hai bisogno di una funzione aggiuntiva 'aMap'? – abatishchev

+0

Per convertire 'Async ' in 'Async '. –

+0

Vedo. Quindi, se posso restituire il "Compito ", allora non ne ho bisogno? – abatishchev