Skip to content

Commit c4db4fa

Browse files
committed
Refactor TaskBuilderBaseRuntime to improve task handling and add BackgroundTaskBuilderRuntime for background execution support
1 parent 9120b7d commit c4db4fa

File tree

1 file changed

+29
-7
lines changed

1 file changed

+29
-7
lines changed

src/IcedTasks/TaskBuilderBase_Net10.fs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ open System.Threading.Tasks
66
open System.Runtime.CompilerServices
77
open Microsoft.FSharp.Core.CompilerServices
88
open System.Collections.Generic
9+
open System.Threading
910

1011
module 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>]
125124
module 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() =
208224
type 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
221239
module TaskBuilder =
222240
open IcedTasks.TaskBase_Net10
223241
let task = TaskBuilderRuntime()
242+
243+
let backgroundTask = BackgroundTaskBuilderRuntime()
244+
245+
let valueTask = ValueTaskBuilderRuntime()

0 commit comments

Comments
 (0)