File tree Expand file tree Collapse file tree
src/FSharpPlus/Extensions Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -163,13 +163,13 @@ module Extensions =
163163 /// at the point where the overall async is started.
164164 /// </remarks >
165165 static member Await ( task : Task < 'T >) : Async < 'T > =
166- Async.FromContinuations ( fun ( sc , ec , cc ) ->
166+ Async.FromContinuations ( fun ( sc , ec , _ ) ->
167167 task.ContinueWith ( fun ( task : Task < 'T >) ->
168168 if task.IsFaulted then
169169 let e = Unchecked.nonNull task.Exception
170170 if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[ 0 ]
171171 else ec e
172- elif task.IsCanceled then cc ( TaskCanceledException ())
172+ elif task.IsCanceled then ec ( TaskCanceledException ())
173173 else sc task.Result)
174174 |> ignore)
175175
@@ -190,13 +190,13 @@ module Extensions =
190190 /// at the point where the overall async is started.
191191 /// </remarks >
192192 static member Await ( task : Task ) : Async < unit > =
193- Async.FromContinuations ( fun ( sc , ec , cc ) ->
193+ Async.FromContinuations ( fun ( sc , ec , _ ) ->
194194 task.ContinueWith ( fun ( task : Task ) ->
195195 if task.IsFaulted then
196196 let e = Unchecked.nonNull task.Exception
197197 if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[ 0 ]
198198 else ec e
199- elif task.IsCanceled then cc ( TaskCanceledException ())
199+ elif task.IsCanceled then ec ( TaskCanceledException ())
200200 else sc ())
201201 |> ignore)
202202
Original file line number Diff line number Diff line change @@ -41,8 +41,9 @@ module Async =
4141 let t2 = createAsync true 0 2
4242 let t3 = createAsync true 0 3
4343
44- let c = new CancellationToken true
45- let t4 = Task.FromCanceled< int> c |> Async.Await
44+ // A genuinely cancelled async: Async.Await no longer surfaces a cancelled Task as a
45+ // cancellation, it raises TaskCanceledException (fslang-suggestions #840).
46+ let t4 : Async < int > = Async.FromContinuations ( fun ( _ , _ , cc ) -> cc ( OperationCanceledException ()))
4647
4748 let t5 = createAsync false 0 5
4849 let t6 = createAsync false 0 6
@@ -71,8 +72,9 @@ module Async =
7172 let t2 = createAsync true 10 2
7273 let t3 = createAsync true 30 3
7374
74- let c = new CancellationToken true
75- let t4 = Task.FromCanceled< int> c |> Async.Await
75+ // A genuinely cancelled async: Async.Await no longer surfaces a cancelled Task as a
76+ // cancellation, it raises TaskCanceledException (fslang-suggestions #840).
77+ let t4 : Async < int > = Async.FromContinuations ( fun ( _ , _ , cc ) -> cc ( OperationCanceledException ()))
7678
7779 let t5 = createAsync false 20 5
7880 let t6 = createAsync false 10 6
Original file line number Diff line number Diff line change @@ -273,6 +273,30 @@ module Task =
273273 Assert.AreEqual ( e0, e1, " Original exception is not the same as that extracted from the Async" )
274274 Assert.AreEqual ( e1, e2, " The exception extracted from the Async is not the same as that extracted from the roundtripped Task" )
275275
276+ [<Test>]
277+ let awaitOfCancelledTaskRaisesTaskCanceledException () =
278+ // A cancelled Task is surfaced through the exception continuation as a TaskCanceledException, so it can be
279+ // caught with an ordinary try/with around the Await, matching C# await (fslang-suggestions #840).
280+ let ct = CancellationToken true
281+
282+ let caughtGeneric =
283+ async {
284+ try
285+ let! _ = Async.Await ( Task.FromCanceled< int> ct)
286+ return false
287+ with : ? TaskCanceledException -> return true }
288+ |> Async.RunSynchronously
289+ Assert.IsTrue ( caughtGeneric, " Await of a cancelled Task<'T> should raise a TaskCanceledException catchable by try/with" )
290+
291+ let caughtNonGeneric =
292+ async {
293+ try
294+ do ! Async.Await ( Task.FromCanceled ct)
295+ return false
296+ with : ? TaskCanceledException -> return true }
297+ |> Async.RunSynchronously
298+ Assert.IsTrue ( caughtNonGeneric, " Await of a cancelled Task should raise a TaskCanceledException catchable by try/with" )
299+
276300
277301 // This module contains tests for ComputationExpression not covered by the below TaskBuilderTests module
278302 module ComputationExpressionTests =
You can’t perform that action at this time.
0 commit comments