Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait without blocking thread? - How?

This is probably one of the most elementary things in F#, but I've just realized I've got no idea what's going on behind the sceens.

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

testMe |> Async.RunSynchronously

What's happening at do! myAsyncFunction()? I'm aware of that it waits for myAsyncFunction to finish, before moving on. But how can it do that, without blocking the thread?

My best guess is that everything after do! myAsyncFunction() is passed along as a continuation, which gets executed on the same thread myAsyncFunction() was scheduled on, once myAsyncFunction() has finished executing.. but then again, that's just a guess.

like image 242
ebb Avatar asked Dec 12 '11 16:12

ebb


People also ask

How do you wait for a thread to end?

We can start threads with the Task class and wait for the threads to finish with the Task. WaitAll() method in C#. In the above code, we waited for the completion of the thread1 and thread2 tasks inside the main thread with the Task. WaitAll() method in C#.

Does thread sleep block java?

Important points of Java Thread Sleep It always suspends the execution of the current thread. The actual thread sleeps until it wakes up, and the execution time depends on the system timers and schedulers. The sleeping thread does not block the current thread.

Why thread sleep is not good?

Thread. sleep is bad! It blocks the current thread and renders it unusable for further work.

Does thread sleep block other threads?

Sleep method causes the current thread to immediately block for the number of milliseconds or the time interval you pass to the method, and yields the remainder of its time slice to another thread. Once that interval elapses, the sleeping thread resumes execution. One thread cannot call Thread. Sleep on another thread.


1 Answers

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

You can understand it better by looking at the desugared version of the code:

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

They key thing is that the asynchronous workflow created by myAsyncFunction is given to the Bind operation that starts it and gives it the second argument (a continuation) as a function to call when the workflow completes. If you simplify a lot, then an asynchronous workflow could be defined like this:

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

So, an asynchronous workflow is just a function that takes some continuations as argument. When it gets the continuations, it does something (i.e. create a timer or start I/O) and then it eventually calls these continuations. The question "On which thread are the continuations called?" is an interesting one - in a simple model, it depends on the MyAsync that you're starting - it may decide to run them anywhere it wants (i.e. Async.SwithcToNewThread runs them on a new thread). The F# library includes some additional handling that makes GUI programming using workflows easier.

Your example uses Async.RunImmediate, which blocks the current thread, but you could also use Async.Start, which just starts the workflow and ignores the result when it is produced. The implementation of Async.Start could look like this:

let Start (async:MyAsync<unit>) = async (ignore, ignore)
like image 158
Tomas Petricek Avatar answered Oct 28 '22 04:10

Tomas Petricek