我搜索了一会儿,发现在Async或Lwt中没有任何明显的东西。
基本上,我有一个(长时间运行的)任务,通常会将其输出写入一个大文件,例如:
let rec foo n = if n < 0 then 0 else (store_result n ; foo (n-1))
现在我想将此计算与客户端同步。
客户端应该能够发出下一个同步点的信号,即:
let rec foo sync n = if n < 0 then 0 else (if n = sync then let sync' = store_result n in foo sync' (n-1) else foo sync (n-1))
因此store_result
会将n
发送给客户端,然后等待sync'
。另一方面,客户端必须发送sync'
,然后等待相应的n
。
此过程应重复,直到计算完成。即客户端可以发送同步点90,50,10,9,......并在每一步获得结果。
我对异步计算有点不熟悉,但我认为有一种优雅的方式来实现整个事情。不幸的是,我无法搜索它,因为我不知道它的名字;)。
那么,解决这个问题最优雅的方法是什么?
答案 0 :(得分:0)
您需要的只是简单bind
和return
(如果是异步)。
基本上,我想如果你的foo
到达sync
,它只能在从客户端获得new sync
之后继续进行,对吗?
所以async中的bind defer todo
让你这样做,你说一旦延迟由异步调度程序完成,让我们计划待办事项。
open Async.Std
let store_result n = Deferred.return (n/2)
let rec foo sync n =
if n < 0 then Deferred.return 0
else
(if n = sync then
Deferred.bind (store_result n) (fun sync' -> foo sync' (n-1))
else
foo sync (n-1))
我建议你阅读https://realworldocaml.org/v1/en/html/concurrent-programming-with-async.html
答案 1 :(得分:0)
以下代码与Lwt和Async同样适用。
let perform_task init n sync =
let rec loop data n =
let data = do_computation data in
if n < 0 then return 0 else
if n <> sync
then loop data (n-1)
else
store_result data >>=
fun () -> loop data (n-1) in
loop init n
我假设,该计算是同步调用的,您需要执行n
次。在同步点上,调用store_result
,创建一个与thunk fun () -> loop data (n-1)
绑定的延迟任务。 store_result
完成后,将立即调用此thunk。
请注意,当loop
变为负数时,n
结束,并使用名为return
的函数返回零。由于您依赖函数中的延迟计算,整个函数的结果也会延迟。
另一个注意事项:您需要open Lwt
或Async.Std
才能访问return
函数和>>=
运算符。后者是bind
函数的同义词。