System.IO.IOException: 'The process cannot access the file'

2

I am trying to synchronize logging to a file in an F Sharp project. Using the lock computational expression I tried to approximate a resource lock, however it seems to not be working.

module regiondeployer.logger

open System
open System.IO
open Microsoft.FSharp.Core
open regiondeployer.personalprojectroot

type private logginglock =
    static member public lock = new Object()

[<Literal>]
let private logfile = personalprojectroot + "log.txt" 

let public initialize() : unit = 
    use init = File.Create(logfile)
    ()

let public logtoconsoleandfile (message:string) : unit =
    lock logginglock.lock (fun _ -> 
        Console.WriteLine message
        use logfilestream = File.AppendText(logfile)
        logfilestream.WriteLine(message)
    )

System.IO.IOException HResult=0x80070020 Message=The process cannot access the file 'log.txt' because it is being used by another process. Source=mscorlib

What am I missing?

.net
multithreading
f#
locking
asked on Stack Overflow Nov 8, 2018 by dcdgo • edited Nov 9, 2018 by dcdgo

1 Answer

7

The problem is that your logginglock.lock is a property with a getter and so a new object is returned each time you access it. As a result, the threads will end up locking different objects and actually access the file concurrently.

If you insist on having the lock object as a field of a static object, then you can define a static field using static let and then just return the object:

type private logginglock() =
    static let _lock = new obj()
    static member public lock = _lock

That said, it would work equally well if you just had the lock object as a global value in a module (as long as it is private to the module). This will likely compile to something very similar as the code above - though there are all sorts of subtleties around locking objects and singletons that I never quite understood...

let private loggingLock = obj()
answered on Stack Overflow Nov 8, 2018 by Tomas Petricek

User contributions licensed under CC BY-SA 3.0