1

我在 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是 aIAsyncOperation<StorageFile>而不是 a预期的StorageFile那样。ReadTextAsync

在 C# 中,您可以执行类似的操作:

var file = await StorageFile.GetFileFromApplicationUriAsync(uri) 

IE

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# 库中可用的东西让它变得更好一些?

4

1 回答 1

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# 核心库很快支持它。

于 2014-04-26T16:20:24.233 回答