Await event to complete before continuing code

Category: visual studio fsharp

Question

WojszaM on Thu, 15 Nov 2018 08:27:09


Hi, I have a question. I have a method that sends and receives messengers via serial port as a byte arrays,

to SerialPort DataRecived I am adding an event that will read response and assign it to type

so basically it should be easy and looks like this:

       async {

            let buffer = Array.zeroCreate<byte> port.ReadBufferSize
            let response = new Response(buffer)
            
            let data_recived =
                async{
                    let! read_buffer = port.AsyncReadLineAsByte()
                    response.Data <- read_buffer

                    printfn "Response Buffer: %A response type: %A" read_buffer response.Data
                } 
                |> Async.RunSynchronously

            port.DataReceived.Add(fun _-> data_recived)

            do! port.AsyncWriteLineAsByte messange 

            //Something to wait for fired event
              
            return response.Data
        }

And type looks like

type Response(buffer: byte[]) =

    let mutable _response = buffer
    
    member this.Data
        with get() = _response
        and set(value) = _response <- value

Between sending messenge and returning byte array i need something that will wait for event to fire and finish so far i tried:

let! args = port.DataReceived |> Async.RunSynchronously

But this get stuck, also i tried:

           while response.Data = buffer
                do printfn "Response: %A \r Buffer: %A" response.Data buffer

Well this works one time, if I send second message it goes to endless loop like this while is fire before event is fired.

Is there any way for this to work?

Replies

Mr. Tines on Thu, 15 Nov 2018 18:58:09


The way I would handle this is to communicate between the threads with a WaitHandle, like

      use sync = new System.Threading.ManualResetEvent(false) // in a suitably long-lived scope
// otherwise `let sync = ...` and
// accept the leak ... async { let buffer = Array.zeroCreate<byte> port.ReadBufferSize let response = new Response(buffer) let data_received = async{ let! read_buffer = port.AsyncReadLineAsByte() response.Data <- read_buffer printfn "Response Buffer: %A response type: %A" read_buffer response.Data sync.Set() |> ignore } |> Async.RunSynchronously port.DataReceived.Add(fun _-> data_received) do! port.AsyncWriteLineAsByte messange sync.WaitOne() |> ignore sync.Reset() |> ignore return response.Data }