【问题标题】:How to make a loop break when using Lwt in OCaml在 OCaml 中使用 Lwt 时如何进行循环中断
【发布时间】:2019-08-03 14:14:34
【问题描述】:

我正在编写代码来监控文件的内容。当程序到达文件末尾时,我希望它干净地终止。

let log () : input_channel Lwt.t = 
  openfile "log" [O_RDONLY] 0 >>= fun fd -> 
  Lwt.return (of_fd input fd);;

let rec loop (ic: input_channel) = Lwt_io.read_line ic >>= fun text -> 
    Lwt_io.printl text >>= fun _ -> loop ic;;

let monitor () : unit Lwt.t = log () >>= loop;;

let handler : exn -> unit Lwt.t = fun e -> match e with
    | End_of_file -> let (p: unit Lwt.t), r = Lwt.wait() in p
    | x -> Lwt.fail x;;

let main () : unit Lwt.t = Lwt.catch monitor handler;;

let _ = Lwt_main.run (main ());;

但是,当读取文件并到达末尾时,程序并没有终止,它只是挂起,我必须用 Ctrl+c 转义。我不确定 bind 的幕后发生了什么,但我想不管它在做什么,最终 Lwt_io.readline ic 最终应该到达文件末尾并返回一个 End_of_file 异常,这可能会被传递给处理程序,等等。

如果我不得不猜测一个分辨率,我想也许在>>= 定义的最后一个绑定中我会包含一些if 检查。但我想我会检查Lwt_io.read_line 是否返回End_of_file,我认为应该由handler 处理。

【问题讨论】:

  • 我对 Lwt 了解不多,但是从天真地阅读代码我并不感到惊讶,因为在 End_of_file 上,您调用 wait,然后扔掉解析器。所以当然它会等待......你为什么不在这里使用return () 而不是在这里?

标签: concurrency ocaml ocaml-lwt


【解决方案1】:

Lwt.wait 函数创建了一个只能使用返回对的第二个元素解析的承诺,基本上,这个函数永远不会终止:

let never_ready () = 
  let (p,_) = Lwt.wait in
  p

这正是你写的。

关于优雅终止,理想情况下,您应该在 loop 函数中执行此操作,以便您可以关闭通道并防止宝贵资源泄漏,例如,

let rec loop (ic: input_channel) = 
  Lwt_io.read_line ic >>= function
  | exception End_of_file -> 
    Lwt.close ic
  | text->
    Lwt_io.printl text >>= fun () -> 
    loop ic

不过,对代码的最小更改是在 handler 的正文中使用 Lwt.return () 而不是 Lwt.wait

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    相关资源
    最近更新 更多