2015-08-09 5 views
7

У меня есть следующий метод интерфейса:Переписывая C# код, используя Task.WhenAll в 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 |> ?? 

Я застрял в последних строках.

Как вернуться к Task<string[]> с F # правильно?

ответ

6

Я должен был догадаться, что тип 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 

Я изменил тип возвращаемого быть Task<string[]> вместо Task<string seq>, как я полагаю, вы хотите сохранить интерфейс. В противном случае я бы посоветовал избавиться от Task и использовать Async в F # -онном коде.

+0

Простите, пропустил описание 'containerClient.GetContainerReference'. Это абстракция поверх «CloudStorageAccount» от Azure SDK. И да, вы правы, фактический тип возврата - «Задача '. Используется для 'Task >', но я изменил это. – abatishchev

+0

То, о чем я не знал, это 'Async.Parallel' и полностью забыл о' return! '. – abatishchev

4

Будет ли это работать?

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 и т.д., так что я не был в состоянии проверить это, но, по крайней мере, он компилирует.

+0

Привет, Марк, спасибо за ваш ответ! Простите, пропустил, чтобы описать, что такое 'containerClient.GetContainerReference()'. Зачем вам нужна дополнительная функция 'aMap'? – abatishchev

+0

Чтобы преобразовать 'Async ' в 'Async '. –

+0

Я вижу. Поэтому, если я могу вернуть 'Task ', тогда мне это не нужно? – abatishchev

Смежные вопросы