@@ -19,33 +19,47 @@ module Task =
1919 elif t.IsCanceled then Canceled
2020 else invalidOp " Internal error: The task is not yet completed."
2121
22+
23+ /// Creates a Task from a value
24+ let result ( value : 'T ) = Task.FromResult value
25+
26+ /// <summary>
27+ /// Raises an exception in the Task
28+ /// </summary>
29+ /// <param name="exn"></param>
30+ let raise < 'T > ( exn : exn ) : Task < 'T > =
31+ match exn with
32+ // AggregateException with multiple exceptions - use TCS
33+ | :? AggregateException as agg when agg.InnerExceptions.Count > 1 ->
34+ let tcs = TaskCompletionSource< 'T>()
35+ tcs.SetException( agg.InnerExceptions)
36+ tcs.Task
37+ // Single non-aggregate exception - use optimized path
38+ // Single exception - use the optimized path
39+ | :? AggregateException as agg -> Task.FromException< 'T> agg.InnerExceptions[ 0 ]
40+ | ex -> Task.FromException< 'T> ex
41+
42+ let private canceledTokenSingleton = CancellationToken true
43+ let private canceled < 'T > : Task < 'T > = Task.FromCanceled< 'T> canceledTokenSingleton
44+
45+
2246 /// <summary>Creates a task workflow from 'source' another, mapping its result with 'f'.</summary>
23- let map ( f : 'T -> 'U ) ( source : Task < 'T >) : Task < 'U > =
47+ let map ( mapper : 'T -> 'U ) ( source : Task < 'T >) : Task < 'U > =
2448 let source = nullArgCheck ( nameof source) source
2549
26- if source.Status = TaskStatus.RanToCompletion then
27- try Task.FromResult ( f source.Result)
28- with e ->
29- let tcs = TaskCompletionSource< 'U> ()
30- tcs.SetException e
31- tcs.Task
50+ if source.IsCompleted then
51+ match source with
52+ | Succeeded r -> try result ( mapper r) with e -> raise< 'U> e
53+ | Faulted exn -> raise< 'U> exn
54+ | Canceled -> canceled< 'U>
3255 else
3356 let tcs = TaskCompletionSource< 'U> ()
34- if source.Status = TaskStatus.Faulted then
35- tcs.SetException ( Unchecked.nonNull source.Exception) .InnerExceptions
36- tcs.Task
37- elif source.Status = TaskStatus.Canceled then
38- tcs.SetCanceled ()
39- tcs.Task
40- else
41- let k = function
42- | Canceled -> tcs.SetCanceled ()
43- | Faulted e -> tcs.SetException e.InnerExceptions
44- | Succeeded r ->
45- try tcs.SetResult ( f r)
46- with e -> tcs.SetException e
47- source.ContinueWith k |> ignore
48- tcs.Task
57+ let k = function
58+ | Canceled -> tcs.SetCanceled ()
59+ | Faulted e -> tcs.SetException e.InnerExceptions
60+ | Succeeded r -> try tcs.SetResult ( mapper r) with e -> tcs.SetException e
61+ source.ContinueWith k |> ignore
62+ tcs.Task
4963
5064 /// <summary>Creates a task workflow from two workflows 'x' and 'y', mapping its results with 'f'.</summary>
5165 /// <remarks>Workflows are run in sequence.</remarks>
@@ -408,13 +422,8 @@ module Task =
408422 ran <- true
409423 try
410424 let task = body ()
411- let rec loop ( task : Task < 'T >) ( compensation : unit -> unit ) =
412- match task.Status with
413- | TaskStatus.RanToCompletion -> compensation (); task
414- | TaskStatus.Faulted -> task.ContinueWith(( fun ( x :Task < 'T >) -> compensation (); x)) .Unwrap ()
415- | TaskStatus.Canceled -> task
416- | _ -> task.ContinueWith(( fun ( x :Task < 'T >) -> ( loop x compensation: Task<_>))) .Unwrap ()
417- loop task compensation
425+ if task.IsCompleted then compensation (); task
426+ else task.ContinueWith( fun ( _ : Task < 'T >) -> compensation (); task) .Unwrap ()
418427 with _ ->
419428 compensation ()
420429 reraise ()
@@ -447,15 +456,8 @@ module Task =
447456 let fallbackTask = nullArgCheck ( nameof fallbackTask) fallbackTask
448457 let source = nullArgCheck ( nameof source) source
449458 orElseWith ( fun _ -> fallbackTask) source
450-
451- /// Creates a Task from a value
452- let result ( value : 'T ) = Task.FromResult value
453459
454- /// Raises an exception in the Task
455- let raise < 'T > ( e : exn ) =
456- let tcs = TaskCompletionSource< 'T> ()
457- tcs.SetException e
458- tcs.Task
460+
459461
460462
461463/// Workaround to fix signatures without breaking binary compatibility.
0 commit comments