Description
In PR #114 (adding support for Async
in Bind
), @bartelink raised the question whether it would be better to use StartImmediateAsTask
instead of StartAsTask
.
Specifically, it is about this part:
let mutable awaiter =
Async
.StartAsTask(asyncSource, cancellationToken = sm.Data.cancellationToken)
.GetAwaiter()
The current approach was taken to mimic the same approach taken for task
in F# Core: https://github.com/dotnet/fsharp/blob/d91b6c5c97accf363d135d1f99816410da4ec341/src/FSharp.Core/tasks.fs#L462, basically:
member inline this.Bind(computation: Async<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> =
this.Bind(Async.StartAsTask computation, continuation)
For comparison, see what was done in async2
, which was poised to be the new async
based on resumable code, like task
is, but unlike task cold-started like the current async
.
So, we have two scenarios:
- use
StartAsTask
to get similar semantics as thetask
CE, but this causes a thread hop - use
StartImmediateAsTask
, which uses the current context
I'm not aware of any downside of using the latter. It definitely saves a thread switch in the general case (note that the thread pool may not always cause a physical thread switch).