@@ -229,7 +229,60 @@ type CancellationType() =
229229yield async { do linkedCts.Dispose() }
230230}
231231 asyncs|> Async.Parallel|> Async.RunSynchronously|> ignore
232-
232+
233+ [<Test>]
234+ member this.AwaitTaskCancellationAfterAsyncTokenCancellation () =
235+ let StartCatchCancellation cancellationToken ( work ) =
236+ Async.FromContinuations( fun ( cont , econt , _ ) ->
237+ // When the child is cancelled, report OperationCancelled
238+ // as an ordinary exception to "error continuation" rather
239+ // than using "cancellation continuation"
240+ let ccont e = econt e
241+ // Start the workflow using a provided cancellation token
242+ Async.StartWithContinuations( work, cont, econt, ccont,
243+ ?cancellationToken= cancellationToken) )
244+
245+ /// Like StartAsTask but gives the computation time to so some regular cancellation work
246+ let StartAsTaskProperCancel taskCreationOptions cancellationToken ( computation : Async < _ >) : System.Threading.Tasks.Task < _ > =
247+ let token = defaultArg cancellationToken Async.DefaultCancellationToken
248+ let taskCreationOptions = defaultArg taskCreationOptions System.Threading.Tasks.TaskCreationOptions.None
249+ let tcs = new System.Threading.Tasks.TaskCompletionSource<_>( " StartAsTaskProperCancel" , taskCreationOptions)
250+
251+ let a =
252+ async {
253+ try
254+ // To ensure we don't cancel this very async (which is required to properly forward the error condition)
255+ let! result = StartCatchCancellation( Some token) computation
256+ do
257+ tcs.SetResult( result)
258+ with exn->
259+ tcs.SetException( exn)
260+ }
261+ Async.Start( a)
262+ tcs.Task
263+
264+ let cts = new CancellationTokenSource()
265+ let tcs = System.Threading.Tasks.TaskCompletionSource<_>()
266+ let t =
267+ async {
268+ do ! tcs.Task|> Async.AwaitTask
269+ }
270+ |> StartAsTaskProperCancel None( Some cts.Token)
271+
272+ // First cancel the token, then set the task as cancelled.
273+ async {
274+ do ! Async.Sleep100
275+ cts.Cancel()
276+ do ! Async.Sleep100
277+ tcs.TrySetException( TimeoutException" Task timed out after token." )
278+ |> ignore
279+ } |> Async.Start
280+
281+ try
282+ let res = t.Wait( 1000 )
283+ Assert.Fail( sprintf" Excepted TimeoutException wrapped in an AggregateException, but got%A " res)
284+ with :? AggregateExceptionas agg-> ()
285+
233286[<Test>]
234287member this.Equality () =
235288let cts1 = new CancellationTokenSource()