Wait without blocking the stream? - How?

This is probably one of the most basic things in F #, but I just realized that I have no idea what is happening behind the sequels.

let testMe() = async { printfn "before!" do! myAsyncFunction() // Waits without blocking thread printfn "after!" } testMe |> Async.RunSynchronously 

What happens at do! myAsyncFunction() do! myAsyncFunction() ? I know that he is waiting for myAsyncFunction complete before moving on. But how to do this without blocking the flow?

My best guess is that everything after do! myAsyncFunction() do! myAsyncFunction() passed as a continuation that runs in the same thread myAsyncFunction() was scheduled as soon as myAsyncFunction() finished executing .., but again, I just think so.

+6
source share
1 answer

As you pointed out correctly, myAsyncFunction is passed a continuation, and it calls it to resume the rest of the asynchronous workflow when it finishes.

You can understand this better by looking at the stiff version of the code:

 let testMe() = async.Delay(fun () -> printfn "before!" async.Bind(myAsyncFunction(), fun () -> printfn "after!" async.Zero())) 

The key point is that the asynchronous workflow created by myAsyncFunction is assigned to the Bind operation, which starts it, and gives it a second argument (continued) as a function to call when the workflow terminates. If you simplify a lot, then an asynchronous workflow can be defined as follows:

 type MyAsync<'T> = (('T -> unit) * (exn -> unit)) -> unit 

So, an asynchronous workflow is just a function that takes some extensions as an argument. When it receives continuations, it does something (i.e., creates a timer or starts I / O), and then ultimately calls these continuations. The question "On what thread are the continuations called?" is interesting - in a simple model, it depends on the MyAsync that you run - it can decide to run them anywhere ( Async.SwithcToNewThread launches them in a new thread). The F # library contains some additional processing that facilitates GUI programming using workflows.

Your example uses Async.RunImmediate , which blocks the current thread, but you can also use Async.Start , which only starts the workflow and ignores the result when it is created. An Async.Start implementation might look like this:

 let Start (async:MyAsync<unit>) = async (ignore, ignore) 
+5
source

Source: https://habr.com/ru/post/903601/


All Articles