jack-pappas / ExtCore

An extended core library for F#.
Apache License 2.0
180 stars 32 forks source link

AsyncChoiceBuilder x.TryFinally / x.Using issue #14

Closed pavel-khritonenko closed 9 years ago

pavel-khritonenko commented 9 years ago

in asyncChoice computation IDisposable.Dispose called after first bind instead of calling on computation finish

open System

let mutable disposed = false

[<SetUp>]
let setup() = disposed <- false

[<TearDown>]
let teardown() =
    printfn "Should be disposed. Checking..."
    Assert.IsTrue(disposed)

type Disposable() = 
    interface IDisposable with
        member x.Dispose() = 
            printfn "disposing!"
            disposed <- true

let createAsyncChoiceDisposable() = async { return Choice1Of2(new Disposable()) }

let waitAsyncChoice() = 
    asyncChoice { 
        printfn "waiting"
    }

let shouldNotBeDisposed() =
    printfn "Should not be disposed. Checking..."
    Assert.IsFalse(disposed)

// asyncChoice wrong behavior

[<Test>]
let usingAsyncChoice() : unit = 
    asyncChoice { 
        use! d = createAsyncChoiceDisposable()
        shouldNotBeDisposed()
        let! a = waitAsyncChoice()
        shouldNotBeDisposed()
    }
    |> Async.RunSynchronously
    |> Choice.get
    |> ignore

// async - expected behavior

let createAsyncDisposable() = async { return (new Disposable()) }

let waitAsync() = 
    async { 
        printfn "waiting"
    }

[<Test>]
let usingAsync() : unit = 
    async { 
        use! d = createAsyncDisposable()
        shouldNotBeDisposed()
        do! waitAsync()
        shouldNotBeDisposed()
    }
    |> Async.RunSynchronously
    |> ignore

I think this problem in TryFinally implementation because target disposed after first bind in case of using try/finally explicit

jack-pappas commented 9 years ago

Thanks Pavel. I'll add this test and look at fixing the AsyncChoice implementation so it disposes the resource at the correct time.

jack-pappas commented 9 years ago

Pavel, this should be fixed now. I'll release a new version of the ExtCore NuGet package later today with the fixes I made for this bug.