Ожидание операции IAsyncOperation в F#

У меня есть следующий код в F#:

   let CreateSampleDataFromJson<'T>(path) = 
      let uri = new Uri(path)
      async {
         let file = StorageFile.GetFileFromApplicationUriAsync(uri)
         let jsonText = FileIO.ReadTextAsync(file)
         return JsonObject<'T>.Parse(jsonText)
      }

У меня проблема в том, что file является IAsyncOperation<StorageFile> и не StorageFile как ReadTextAsync надеется.

В C# вы можете сделать что-то похожее на это:

var file = await StorageFile.GetFileFromApplicationUriAsync(uri) 

т.е.

public async Task<T> CreateSampleDataFromUrl<T>(string path)
{
  var uri = new Uri(path);
  var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
  var jsonText = await FileIO.ReadTextAsync(file);
  return JsonObject<T>.Parse(jsonText);
}

Проблема в том, что я не знаю, как ждать IAsyncOperation в F#. Обычный let! не работает то есть следующее не компилируется:

async {
   let! file = StorageFile.GetFileFromApplicationUriAsync(uri)

С ошибкой компилятора:

error FS0001: This expression was expected to have type    Async<'a>    but here has type    IAsyncOperation<StorageFile>

Я нашел документ, в котором говорится, что есть AsTask() метод расширения, определенный в System.WindowsRuntimeSystemExtensions класс, который я могу использовать следующим образом:

 let! file = StorageFile.GetFileFromApplicationUriAsync(uri).AsTask() |> Async.AwaitTask

Есть ли стандартный способ сделать это или что-то доступное в библиотеке F# где-нибудь, что делает это немного лучше?

1 ответ

Решение

Ваше решение мне кажется хорошим. Если вы ищете более приятный синтаксис, как насчет того, чтобы свернуть его в функцию, подобную этой (без каких-либо необоснованных аннотаций типов):

let await<'a> (op: IAsyncOperation<'a>) : Async<'a> =
   op.AsTask() |> Async.AwaitTask

Это даст вам почти такой же синтаксис, который вы видели бы в C#:

async {
   let! file = await <| StorageFile.GetFileFromApplicationUriAsync(uri)
   ...
}

Ошибки компилятора, которые вы получали с вашими предыдущими подходами, следует ожидать. Все, что касается асинхронного рабочего процесса, - это F#-специфический тип асинхронности. Этот тип дает вам возможность взаимодействовать с остальным миром.NET с помощью задач, но это все. IAsyncOperation из "другой части мира", я не ожидаю, что основные библиотеки F# поддержат ее в ближайшее время.

Другие вопросы по тегам