@@ -14,10 +14,11 @@ module Task =
1414
1515 /// Active pattern to match the state of a completed Task
1616 let inline internal (| Succeeded | Canceled | Faulted |) ( t : Task < 'a >) =
17- if t.IsCompletedSuccessfully then Succeeded t.Result
18- elif t.IsFaulted then Faulted ( Unchecked.nonNull t.Exception)
19- elif t.IsCanceled then Canceled
20- else invalidOp " Internal error: The task is not yet completed."
17+ match t.Status with
18+ | TaskStatus.RanToCompletion -> Succeeded t.Result
19+ | TaskStatus.Faulted -> Faulted ( Unchecked.nonNull t.Exception)
20+ | TaskStatus.Canceled -> Canceled
21+ | _ -> invalidOp ( sprintf " Internal error: The task is not yet in a final state. State = TaskStatus.%A " t.Status)
2122
2223 let inline internal continueTask ( tcs : TaskCompletionSource < 'Result >) ( k : 't -> unit ) ( x : Task < 't >) =
2324 let f = function
@@ -26,32 +27,56 @@ module Task =
2627 | Canceled -> tcs.SetCanceled ()
2728 x.ConfigureAwait( false ) .GetAwaiter() .UnsafeOnCompleted ( fun () -> f x)
2829
30+ #if NET5_ 0_ OR_ GREATER
31+ let [<Literal>] private tcsOptions = TaskCreationOptions.RunContinuationsAsynchronously
32+ #else
33+ let private tcsOptions = ()
34+ #endif
2935
3036 /// <summary >Creates a Task that's completed successfully with the specified value.</summary >
3137 /// <param name =" value " ></param >
3238 /// <returns >A Task that is completed successfully with the specified value.</returns >
3339 let result ( value : 'T ) : Task < 'T > = Task.FromResult value
34-
40+
41+
42+ /// <summary >Creates a Task that's completed unsuccessfully with the specified exception.</summary >
43+ /// <param name =" exn " >The exception to be raised.</param >
44+ /// <returns >A Task that is completed unsuccessfully with the specified exception.</returns >
45+ let raise < 'T > ( exn : exn ) : Task < 'T > =
46+ #if NET5_ 0_ OR_ GREATER
47+ Task.FromException< 'T> exn
48+ #else
49+ let tcs = TaskCompletionSource< 'T> tcsOptions
50+ tcs.SetException exn
51+ tcs.Task
52+ #endif
53+
3554 /// <summary >Creates a Task that's completed unsuccessfully with the specified exceptions.</summary >
36- /// <param name =" exn " >The AggregateException to be raised.</param >
55+ /// <param name =" aex " >The AggregateException to be raised.</param >
3756 /// <returns >A Task that is completed unsuccessfully with the specified exceptions.</returns >
3857 /// <remarks >
3958 /// Prefer this function to handle AggregateExceptions over Task.FromException as it handles them correctly.
4059 /// </remarks >
4160 let inline internal FromExceptions < 'T > ( aex : AggregateException ) : Task < 'T > =
61+ #if NET5_ 0_ OR_ GREATER
4262 match aex with
4363 | agg when agg.InnerExceptions.Count = 1 -> Task.FromException< 'T> agg.InnerExceptions[ 0 ]
44- | agg ->
45- let tcs = TaskCompletionSource< 'T> ()
46- tcs.SetException agg.InnerExceptions
64+ | _ ->
65+ #endif
66+ let tcs = TaskCompletionSource< 'T> tcsOptions
67+ tcs.SetException aex.InnerExceptions
4768 tcs.Task
4869
49- let private cancellationTokenSingleton = CancellationToken true
50-
5170 /// <summary >Creates a Task that's canceled.</summary >
5271 /// <returns >A Task that's canceled.</returns >
53- let canceled < 'T > : Task < 'T > = Task.FromCanceled< 'T> cancellationTokenSingleton
54-
72+ let canceled < 'T > : Task < 'T > =
73+ #if NET5_ 0_ OR_ GREATER
74+ Task.FromCanceled< 'T> ( CancellationToken true )
75+ #else
76+ let tcs = TaskCompletionSource< 'T> tcsOptions
77+ tcs.SetCanceled ()
78+ tcs.Task
79+ #endif
5580
5681 /// <summary >Creates a task workflow from 'source' workflow, mapping its result with 'mapper'.</summary >
5782 /// <param name =" mapper " >The mapping function.</param >
@@ -62,11 +87,11 @@ module Task =
6287
6388 if source.IsCompleted then
6489 match source with
65- | Succeeded r -> try result ( mapper r) with e -> Task.FromException <_> e
90+ | Succeeded r -> try result ( mapper r) with e -> raise e
6691 | Faulted exn -> FromExceptions exn
6792 | Canceled -> canceled
6893 else
69- let tcs = TaskCompletionSource< 'U> TaskCreationOptions.RunContinuationsAsynchronously
94+ let tcs = TaskCompletionSource< 'U> tcsOptions
7095 source |> continueTask tcs ( fun r -> try tcs.SetResult ( mapper r) with e -> tcs.SetException e)
7196 tcs.Task
7297
@@ -81,13 +106,13 @@ module Task =
81106
82107 if task1.IsCompleted && task2.IsCompleted then
83108 match task1, task2 with
84- | Succeeded r1, Succeeded r2 -> try result ( mapper r1 r2) with e -> Task.FromException <_> e
109+ | Succeeded r1, Succeeded r2 -> try result ( mapper r1 r2) with e -> raise e
85110 | Succeeded _ , Faulted exn -> FromExceptions exn
86111 | Succeeded _ , Canceled -> canceled
87112 | Faulted exn , _ -> FromExceptions exn
88113 | Canceled , _ -> canceled
89114 else
90- let tcs = TaskCompletionSource< 'U> TaskCreationOptions.RunContinuationsAsynchronously
115+ let tcs = TaskCompletionSource< 'U> tcsOptions
91116
92117 match task1.Status, task2.Status with
93118 | TaskStatus.Canceled, _ -> tcs.SetCanceled ()
@@ -112,15 +137,15 @@ module Task =
112137
113138 if task1.IsCompleted && task2.IsCompleted && task3.IsCompleted then
114139 match task1, task2, task3 with
115- | Succeeded r1, Succeeded r2, Succeeded r3 -> try result ( mapper r1 r2 r3) with e -> Task.FromException <_> e
140+ | Succeeded r1, Succeeded r2, Succeeded r3 -> try result ( mapper r1 r2 r3) with e -> raise e
116141 | Faulted exn , _ , _ -> FromExceptions exn
117142 | Canceled , _ , _ -> canceled
118143 | _ , Faulted exn , _ -> FromExceptions exn
119144 | _ , Canceled , _ -> canceled
120145 | _ , _ , Faulted exn -> FromExceptions exn
121146 | _ , _ , Canceled -> canceled
122147 else
123- let tcs = TaskCompletionSource< 'U> TaskCreationOptions.RunContinuationsAsynchronously
148+ let tcs = TaskCompletionSource< 'U> tcsOptions
124149 match task1.Status, task2.Status, task3.Status with
125150 | TaskStatus.Canceled, _ , _ -> tcs.SetCanceled ()
126151 | TaskStatus.Faulted , _ , _ -> tcs.SetException ( Unchecked.nonNull task1.Exception) .InnerExceptions
@@ -147,9 +172,9 @@ module Task =
147172 let task2 = nullArgCheck ( nameof task2) task2
148173
149174 if task1.Status = TaskStatus.RanToCompletion && task2.Status = TaskStatus.RanToCompletion then
150- try result ( mapper task1.Result task2.Result) with e -> Task.FromException < 'U > e
175+ try result ( mapper task1.Result task2.Result) with e -> raise e
151176 else
152- let tcs = TaskCompletionSource<_> ()
177+ let tcs = TaskCompletionSource<_> tcsOptions
153178 let r1 = ref Unchecked.defaultof<_>
154179 let r2 = ref Unchecked.defaultof<_>
155180 let mutable cancelled = false
@@ -195,9 +220,9 @@ module Task =
195220
196221 if task1.Status = TaskStatus.RanToCompletion && task2.Status = TaskStatus.RanToCompletion && task3.Status = TaskStatus.RanToCompletion then
197222 try result ( mapper task1.Result task2.Result task3.Result)
198- with e -> Task.FromException < 'U > e
223+ with e -> raise e
199224 else
200- let tcs = TaskCompletionSource<_> ()
225+ let tcs = TaskCompletionSource<_> tcsOptions
201226 let r1 = ref Unchecked.defaultof<_>
202227 let r2 = ref Unchecked.defaultof<_>
203228 let r3 = ref Unchecked.defaultof<_>
@@ -241,13 +266,13 @@ module Task =
241266
242267 if f.IsCompleted && x.IsCompleted then
243268 match f, x with
244- | Succeeded r1, Succeeded r2 -> try result ( r1 r2) with e -> Task.FromException <_> e
269+ | Succeeded r1, Succeeded r2 -> try result ( r1 r2) with e -> raise e
245270 | Succeeded _ , Faulted exn -> FromExceptions exn
246271 | Succeeded _ , Canceled -> canceled
247272 | Faulted exn , _ -> FromExceptions exn
248273 | Canceled , _ -> canceled
249274 else
250- let tcs = TaskCompletionSource< 'U> TaskCreationOptions.RunContinuationsAsynchronously
275+ let tcs = TaskCompletionSource< 'U> tcsOptions
251276 match f.Status, x.Status with
252277 | TaskStatus.Canceled, _ -> tcs.SetCanceled ()
253278 | TaskStatus.Faulted, _ -> tcs.SetException ( Unchecked.nonNull f.Exception) .InnerExceptions
@@ -271,7 +296,7 @@ module Task =
271296 | Faulted exn , _ -> FromExceptions exn
272297 | Canceled , _ -> canceled
273298 else
274- let tcs = TaskCompletionSource< 'T1 * 'T2> ()
299+ let tcs = TaskCompletionSource< 'T1 * 'T2> tcsOptions
275300 match task1.Status, task2.Status with
276301 | TaskStatus.Canceled, _ -> tcs.SetCanceled ()
277302 | TaskStatus.Faulted, _ -> tcs.SetException ( Unchecked.nonNull task1.Exception) .InnerExceptions
@@ -313,11 +338,12 @@ module Task =
313338 let ignore ( source : Task ) =
314339 let source = nullArgCheck ( nameof source) source
315340
316- if source.IsCompletedSuccessfully then result ()
317- elif source.IsFaulted then FromExceptions ( Unchecked.nonNull source.Exception)
318- elif source.IsCanceled then canceled
319- else
320- let tcs = TaskCompletionSource< unit> ()
341+ match source.Status with
342+ | TaskStatus.RanToCompletion -> result ()
343+ | TaskStatus.Faulted -> FromExceptions ( Unchecked.nonNull source.Exception)
344+ | TaskStatus.Canceled -> canceled
345+ | _ ->
346+ let tcs = TaskCompletionSource< unit> tcsOptions
321347 let k ( t : Task ) : unit =
322348 if t.IsCanceled then tcs.SetCanceled ()
323349 elif t.IsFaulted then tcs.SetException ( Unchecked.nonNull source.Exception) .InnerExceptions
@@ -329,7 +355,7 @@ module Task =
329355 let rec tryWith ( body : unit -> Task < 'T >) ( compensation : exn -> Task < 'T >) : Task < 'T > =
330356 let runCompensation exn =
331357 try compensation exn
332- with e -> Task.FromException < 'T > e
358+ with e -> raise e
333359 let unwrapException ( agg : AggregateException ) =
334360 if agg.InnerExceptions.Count = 1 then agg.InnerExceptions.[ 0 ]
335361 else agg :> Exception
@@ -353,12 +379,12 @@ module Task =
353379 try
354380 compensation ()
355381 reraise ()
356- with e -> Task.FromException < 'T > e
382+ with e -> raise e
357383 if task.IsCompleted then
358384 try
359385 compensation ()
360386 task
361- with e -> Task.FromException < 'T > e
387+ with e -> raise e
362388 else
363389 task.ContinueWith( fun ( x : Task < 'T >) -> tryFinally ( fun () -> x) compensation) .Unwrap ()
364390
@@ -401,7 +427,7 @@ module Task =
401427 let inline recover ( [<InlineIfLambda>] mapper : exn -> 'T ) ( source : Task < 'T >) : Task < 'T > =
402428 let source = nullArgCheck ( nameof source) source
403429
404- tryWith ( fun () -> source) ( mapper >> Task.FromResult )
430+ tryWith ( fun () -> source) ( mapper >> result )
405431
406432 /// <summary >Maps the exception of a faulted task to another exception.</summary >
407433 /// <param name =" mapper " >Mapping function from exception to exception.</param >
@@ -415,7 +441,7 @@ module Task =
415441 | Faulted exn -> FromExceptions ( AggregateException ( mapper exn))
416442 | _ -> source
417443 else
418- let tcs = TaskCompletionSource< 'T> TaskCreationOptions.RunContinuationsAsynchronously
444+ let tcs = TaskCompletionSource< 'T> tcsOptions
419445 let k = function
420446 | Succeeded r -> tcs.SetResult r
421447 | Faulted aex -> tcs.SetException ( AggregateException ( mapper aex)) .InnerExceptions
@@ -430,13 +456,8 @@ module Task =
430456 /// <returns >The resulting Task.</returns >
431457 let ofResult ( source : Result < 'T , exn >) : Task < 'T > =
432458 match source with
433- | Ok x -> Task.FromResult x
434- | Error exn -> Task.FromException< 'T> exn
435-
436- /// <summary >Creates a Task that's completed unsuccessfully with the specified exception.</summary >
437- /// <param name =" exn " >The exception to be raised.</param >
438- /// <returns >A Task that is completed unsuccessfully with the specified exception.</returns >
439- let raise < 'T > ( exn : exn ) : Task < 'T > = Task.FromException< 'T> exn
459+ | Ok x -> result x
460+ | Error exn -> raise exn
440461
441462
442463/// Workaround to fix signatures without breaking binary compatibility.
0 commit comments