如何等待Async方法,类似于C#

时间:2017-12-12 20:28:40

标签: f#

如何在F#中进行简单的等待

在C#中,我有这样的代码:

Measure = IF(COUNTROWS(ALLSELECTED(Report[Shipment Group])) = 1, "Something which would not filter the units", SELECTEDVALUE(Report[Units], SUM(Report[Units])))

所以我创建了一个让await = ... 到我的F#代码变得与我的C#代码更相似。

我目前的F#代码是:

await collection.InsertOneAsync(DO);
var r = collection.ReplaceOneAsync((fun d -> d.Id = DO.Id), DO)

我想只有一个await(awaits)的定义,但我能做的最好的就是这个,因为在Insere上,type是Task,但在Salva上,type是Task<'T>

如果我只使用等待,我会收到此编译错误:

  

FS0001类型'Threading.Tasks.Task'与'Threading.Tasks.Task<'a>'

类型不兼容

如果我只使用等待,则会进行编译,但我会从异步任务中丢失返回类型 我想将await和awaits合并为一个

let awaits (t: Threading.Tasks.Task) = t |> Async.AwaitTask |> Async.RunSynchronously
let await (t: Threading.Tasks.Task<'T>) = t |> Async.AwaitTask |> Async.RunSynchronously


let Busca (numero) = 
    let c = collection.Find(fun d -> d.Numero=numero).ToList()
    c

let Insere(DO: DiarioOficial) =
    //collection.InsertOneAsync(DO) |> Async.AwaitTask |> Async.RunSynchronously
    collection.InsertOneAsync(DO) |> awaits

let Salva (DO: DiarioOficial) =
    //let r = collection.ReplaceOneAsync((fun d -> d.Id = DO.Id), DO) |> Async.AwaitTask |> Async.RunSynchronously
    let r = collection.ReplaceOneAsync((fun d -> d.Id = DO.Id), DO) |> await
    r

我该怎么做?

2 个答案:

答案 0 :(得分:3)

在F#中,我们倾向于使用另一种语法。例如描述了在这里:https://fsharpforfunandprofit.com/posts/concurrency-async-and-parallel/.

或此处:https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/asynchronous-and-concurrent-programming/async

使用C#Tasks的想法是将它们“转换”为异步Async.Await<'T>

你可以采取另一种方式,但这是最直接的。

答案 1 :(得分:2)

在F#和C#中编写异步代码有两个部分。

  • 您需要将方法或代码块标记为异步。在C#中,这是使用async关键字完成的。 F#等价物是使用async { ... }块(这是一个表达式,但除此之外,它是相似的)。

  • async方法或async { .. }块中,您可以进行非阻止调用。在C#中,这是使用await完成的,在F#中使用let!完成。请注意,这不仅仅是一个函数调用 - 编译器以特殊方式处理它。

F#也使用Async<T>类型而不是Task<T>,但这些很容易转换 - 例如使用Async.AwaitTask。所以,你可能想要这样的东西:

let myAsyncFunction () = async {
  let! _ = collection.InsertOneAsync(DO) |> Async.AwaitTask
  let r = collection.ReplaceOneAsync((fun d -> d.Id = DO.Id), DO) 
  // More code goes here
}

我使用let!来表达这个想法,但是如果你有一个返回unit的异步操作,你也可以使用do!

do! collection.InsertOneAsync(DO) |> Async.AwaitTask