Asynchronous workflow
Last updated
Was this helpful?
Last updated
Was this helpful?
Do not block the current thread while waiting for a long calculation
Allow parallel calculations
Indicate that a calculation may take some time
Async<'T>
typeRepresents an asynchronous calculation
π Similar to the async/await
pattern way before Cβ― and JS
2007: Async<'T>
Fβ―
2012: Task<T>
.NET and pattern async
/await
2017: Promise
JavaScript and pattern async
/await
Async
objectAsync.AwaitTask(task : Task or Task<'T>) : Async<'T>
β Convert a Task
(.NET) to Async
(Fβ―)
Async.Sleep(milliseconds or TimeSpan) : Async<unit>
β await Task.Delay()
β Thread.Sleep
β does not block current thread
FSharp.Control CommonExtensions
module: extends the System.IO.Stream
type ()
β AsyncRead(buffer: byte[], ?offset: int, ?count: int) : Async<int>
β AsyncWrite(buffer: byte[], ?offset: int, ?count: int) : Async<unit>
Async.RunSynchronously(calc: Async<'T>, ?timeoutMs: int, ?cancellationToken) : 'T
β Waits for the calculation to end, blocking the calling thread! (β await
Cβ―) β οΈ
Async.Start(operation: Async<unit>, ?cancellationToken) : unit
β Perform the operation in the background (without blocking the calling thread)
β οΈ If an exception occurs, it is "swallowed"!
Async.StartImmediate(calc: Async<'T>, ?cancellationToken) : unit
β Perform the calculation in the calling thread!
Async.StartWithContinuations(calc, continuations..., ?cancellationToken)
β Ditto Async.RunSynchronously
β οΈ ... with 3 callbacks of continuation:
β on success β
, exception π₯ and cancellation π
async { expression }
blockA.k.a. Async workflow
Syntax for sequentially writing an asynchronous calculation
β The result of the calculation is wrapped in an Async
object
Keywords
return
β final value of calculation β’ unit
if omitted
let!
β access to the result of an async sub-calculation (β await
in Cβ―)
use!
β ditto use
(management of an IDisposable
) + let!
do!
β ditto let!
for async calculation without return (Async<unit>
)
Let's compare an Fβ― async function...
... with its equivalent Cβ― async method:
We can see the following equivalence regarding keywords and types:
Async<int>
type
Task<int>
type
async {...}
block
async
method keyword
let!
keyword
var
and await
keywords
do!
keyword
await
keyword
Async.RunSynchronously
Async.RunSynchronously
runs the calculation and returns the result BUT blocks the calling thread! Use it only at the "end of the chain" and not to unwrap intermediate asynchronous calculations! Use an async
block instead.
Async.Parallel(computations: Async<'T> seq, ?maxDegreeOfParallelism) : Async<'T array>
Fork: calculations run in parallel
Use the optional maxDegreeOfParallelism
to throttle/limit the number of concurrently executing tasks ; it's like WithDegreeOfParallelism(throttle)
in LINQ and ParallelEnumerable
.
Wait for all calculations to finish
Join: aggregation of results
In the same order as calculations
β οΈ All calculations must return the same type!
Async.StartChild(calc: Async<'T>, ?timeoutMs: int) : Async<Async<'T>>
Allows several operations to be run in parallel
β ... whose results are of different types (β Async.Parallel
)
Used in async
block with 2 let!
per child calculation (cf. Async<Async<'T>>
)
Shared cancellation π β Child calculation shares cancellation token with its parent calculation
Example:
Let's first define a function delay
β which returns the specified value x
β after ms
milliseconds
Timing results:
inSeries
00:00:00.323
00:00:00.015
inParallel
00:00:00.218
00:00:00.031
β inParallel
is working, longing ~200ms vs ~300ms for inSeries
.
β inParallel
uses 2 times more CPU than inSeries
.
Based on a default or explicit CancellationToken/Source
:
Async.RunSynchronously(computation, ?timeout, ?cancellationToken)
Async.Start(computation, ?cancellationToken)
Trigger cancellation
Explicit token + cancellationTokenSource.Cancel()
Explicit token with timeout new CancellationTokenSource(timeout)
Default token: Async.CancelDefaultToken()
β OperationCanceledException
π£
Check cancellation
Implicit: at each keyword in async block: let
, let!
, for
...
Explicit local: let! ct = Async.CancellationToken
then ct.IsCancellationRequested
.
Explicit global: Async.OnCancel(callback)
Example:
CT = Cancellation Token CTS = Cancellation Token Source
do!
, let!
... in async {}
Any?
Async.StartChild
Parallel operations
Async.Start
Fire & forget: send a message to a bus...
Async.StartImmediately
?
Async.RunSynchronously
Program root, scripting...
FSharp.Control WebExtensions
module: extends type System.Net.WebClient
()
β AsyncDownloadData(address : Uri) : Async<byte[]>
β AsyncDownloadString(address : Uri) : Async<string
β Task.WhenAll
:
We will test the following script in the console FSI, using the #time
FSI directive ().
Adapted from π , by AndrΓ© Silva