Wojciech Szabowicz
Wojciech Szabowicz

Reputation: 4198

f# timeout when using Async.RunSynchronously

I am new to f# and I have a question about timeout in asynchornization operations, this is simple communication using serial com ports, so I have a method/function:

    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

All communication (messengering) is controlled in this module:

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
    }

Basically this works fine, it sends a message and receives response, But now I want to add a timeout, in case i am connect. I tried to fiddle with

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

but with no luck. As i see in documentation it takes timeout and cancellation token and Async, What would be this T0 generic parameter in my case?

Upvotes: 1

Views: 177

Answers (1)

Tarmil
Tarmil

Reputation: 11362

What happens is that Async.RunSynchronously is a static method, rather than a method function, so it takes its arguments with tuple syntax. So you can't partially apply it and pipe the last argument into it.

You can do this:

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

or if you really want to pipe:

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

Upvotes: 4

Related Questions