@@ -6,6 +6,7 @@ open System.Threading.Tasks
66open System.Runtime .CompilerServices
77open Microsoft.FSharp .Core .CompilerServices
88open System.Collections .Generic
9+ open System.Threading
910
1011module internal AsyncHelpers =
1112
@@ -25,11 +26,9 @@ type TaskBuilderBaseRuntime() =
2526 ValueTask.FromResult value
2627 |> Awaitable.GetAwaiter
2728
28- // [<NoEagerConstraintApplication>]
2929 member inline _.Bind ( awaiter , [<InlineIfLambda>] continuation ) =
3030 AsyncHelpers.awaitAwaiter awaiter
3131 |> continuation
32- // |> Awaitable.GetAwaiter
3332
3433
3534 // [<NoEagerConstraintApplication>]
@@ -47,7 +46,7 @@ type TaskBuilderBaseRuntime() =
4746 // [<NoEagerConstraintApplication>]
4847 member inline this.MergeSources ( awaiter1 , awaiter2 ) =
4948 this.Bind( awaiter1, fun v1 -> this.Bind( awaiter2, fun v2 -> this.Return( struct ( v1, v2))))
50- // |> Awaitable.GetAwaiter
49+
5150
5251 member inline this.Combine ( awaiter1 , [<InlineIfLambda>] continuation ) =
5352 this.Bind( awaiter1, fun _ -> continuation ())
@@ -123,7 +122,6 @@ type TaskBuilderBaseRuntime() =
123122
124123[<AutoOpen>]
125124module LowPriority =
126- // let task2 = TaskBuilderBaseRuntime()
127125
128126 type TaskBuilderBaseRuntime with
129127
@@ -145,7 +143,7 @@ module LowPriority =
145143 ///
146144 /// <returns>'Awaiter</returns>
147145 // [<NoEagerConstraintApplication>]
148- member inline _.Source < 'Awaitable , 'TResult1 , 'TResult2 , ' Awaiter, 'TOverall
146+ member inline _.Source < 'Awaitable , 'TResult1 , 'Awaiter
149147 when Awaitable < 'Awaitable , 'Awaiter , 'TResult1 >>
150148 ( awaitable : 'Awaitable )
151149 : 'Awaiter =
@@ -198,7 +196,25 @@ type TaskBuilderRuntime() =
198196 member inline this.Run ( [<InlineIfLambda>] f : unit -> 'a ) : Task < 'T > =
199197 AsyncHelpers.awaitAwaiter ( f ())
200198 |> Task.FromResult
201- // f().AsTask()
199+
200+ /// Used to force type inference to prefer Task<_> for parameters of functions using the build
201+ member inline _.Source ( task : Task < 'T >) = Awaitable.GetTaskAwaiter task
202+
203+
204+ type BackgroundTaskBuilderRuntime () =
205+ inherit TaskBuilderBaseRuntime()
206+
207+ member inline this.Run ( [<InlineIfLambda>] f : unit -> 'a ) : Task < 'T > =
208+ // backgroundTask { .. } escapes to a background thread where necessary
209+ // See spec of ConfigureAwait(false) at https://devblogs.microsoft.com/dotnet/configureawait-faq/
210+ if
211+ isNull SynchronizationContext.Current
212+ && obj.ReferenceEquals( TaskScheduler.Current, TaskScheduler.Default)
213+ then
214+ AsyncHelpers.awaitAwaiter ( f ())
215+ |> Task.FromResult
216+ else
217+ Task.Run< 'T>( fun () -> AsyncHelpers.awaitAwaiter ( f ()))
202218
203219
204220 /// Used to force type inference to prefer Task<_> for parameters of functions using the build
@@ -208,7 +224,9 @@ type TaskBuilderRuntime() =
208224type ValueTaskBuilderRuntime () =
209225 inherit TaskBuilderBaseRuntime()
210226
211- member inline this.Run ( [<InlineIfLambda>] f : unit -> ValueTask < 'T >) : ValueTask < 'T > = f ()
227+ member inline this.Run ( [<InlineIfLambda>] f ) : ValueTask < 'T > =
228+ AsyncHelpers.awaitAwaiter ( f ())
229+ |> ValueTask.FromResult
212230
213231
214232 /// Used to force type inference to prefer ValueTask<_> for parameters of functions using the build
@@ -221,3 +239,7 @@ namespace IcedTasks.Polyfill.TasksRuntime
221239module TaskBuilder =
222240 open IcedTasks.TaskBase_Net10
223241 let task = TaskBuilderRuntime()
242+
243+ let backgroundTask = BackgroundTaskBuilderRuntime()
244+
245+ let valueTask = ValueTaskBuilderRuntime()
0 commit comments