Skip to content

Commit

Permalink
Dispose when async workflow is cancelled (#1555)
Browse files Browse the repository at this point in the history
* Add test for #1436

* Dispose when async workflow is cancelled
  • Loading branch information
mrinaldi authored and KevinRansom committed Sep 23, 2016
1 parent bcf53a9 commit 7ea2852
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,28 @@ type AsyncModule() =
Assert.IsTrue(isSet())
for _i = 1 to 3 do test()

[<Test>]
member this.``OnCancel.RaceBetweenCancellationAndDispose``() =
let flag = ref 0
let cts = new System.Threading.CancellationTokenSource()
let go = async {
use disp =
cts.Cancel()
{ new IDisposable with
override __.Dispose() = incr flag }
while true do
do! Async.Sleep 50
}
try
Async.RunSynchronously (go, cancellationToken = cts.Token)
with
#if FX_NO_OPERATION_CANCELLED
_ -> ()
#else
:? System.OperationCanceledException -> ()
#endif
Assert.AreEqual(1, !flag)

[<Test>]
member this.``OnCancel.CancelThatWasSignalledBeforeRunningTheComputation``() =
let test() =
Expand Down
6 changes: 5 additions & 1 deletion src/fsharp/FSharp.Core/control.fs
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,11 @@ namespace Microsoft.FSharp.Control

/// Implement use/Dispose
let usingA (r:'T :> IDisposable) (f:'T -> Async<'a>) : Async<'a> =
tryFinallyA (fun () -> Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.Dispose r) (callA f r)
let mutable x = 0
let disposeFunction _ =
if Interlocked.CompareExchange(&x, 1, 0) = 0 then
Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.Dispose r
tryFinallyA disposeFunction (callA f r) |> whenCancelledA disposeFunction

let ignoreA p =
bindA p (fun _ -> doneA)
Expand Down

0 comments on commit 7ea2852

Please sign in to comment.