使用Async.RunSynchronously时f#超时

时间:2018-11-05 14:25:29

标签: f#

我是f#的新手,我对异步操作中的超时有疑问,这是使用串行com端口的简单通信,因此我有一种方法/功能:

    let SendMessenge(port : Ports.SerialPort, messange: string) =

       async {
        do! port.AsyncWriteLine messange
        let! response = port.AsyncReadLine() // this returns a string

        return response
       }
      |> Async.RunSynchronously // the place i fiddled with

所有通信(信使)都在此模块中控制:

type SerialPort with

  member this.AsyncWriteLine(messange : string) = this.BaseStream.AsyncWrite(this.Encoding.GetBytes(messange + "\n"))

    member this.AsyncReadLine() =

    async {
      let messange_builder = StringBuilder()

      let buffer_ref = ref (Array.zeroCreate<byte> this.ReadBufferSize)
      let buffer = !buffer_ref
      let last_char = ref 0uy

      while !last_char <> byte '\n' do

        let! readCount = this.BaseStream.AsyncRead buffer
        last_char := buffer.[readCount-1]
        messange_builder.Append (this.Encoding.GetString(buffer.[0 .. readCount-1])) |> ignore

      messange_builder.Length <- messange_builder.Length-1 

      let response : string = messange_builder.ToString()

      printfn "Response: %s" response

      return response
    }

基本上可以正常工作,它发送一条消息并接收响应,但是现在我想添加一个超时,以防我连接。我试图摆弄

|> Async.RunSynchronously(???, timeout, cancel_token)

但是没有运气。正如我在文档中看到的那样,它需要超时和取消令牌以及Async,就我而言,这个T0通用参数是什么?

1 个答案:

答案 0 :(得分:4)

发生的情况是Async.RunSynchronously是静态方法,而不是方法函数,因此它采用元组语法作为参数。因此,您不能部分应用它并将最后一个参数传递给它。

您可以这样做:

let response = async {
  // ...
}
Async.RunSynchronously(response, timeout, cancel_token)

或者如果您真的要管道:

async {
  // ...
}
|> fun response -> Async.RunSynchronously(response, timeout, cancel_token)