【问题标题】:System.IO.IOException: 'The process cannot access the file'System.IO.IOException: '进程无法访问文件'
【发布时间】:2018-11-08 23:07:58
【问题描述】:

我正在尝试将日志记录同步到 F Sharp 项目中的文件。使用锁计算表达式我试图近似一个资源锁,但它似乎不起作用。

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 消息=进程 无法访问文件 '日志.txt' 因为它正在被另一个进程使用。来源=mscorlib

我错过了什么?

【问题讨论】:

  • 这是在 Windows 上还是在 Linux 上?这两个操作系统使用不同的文件锁定模型,所以在 Linux 上运行良好的东西不一定在 Windows 上运行。

标签: .net multithreading f# locking


【解决方案1】:

问题是您的logginglock.lock 是一个带有getter 的属性,因此每次访问它时都会返回一个新对象。结果,线程最终会锁定不同的对象并实际同时访问文件。

如果你坚持要把锁对象作为静态对象的一个​​字段,那么你可以使用static let定义一个静态字段,然后直接返回对象:

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

也就是说,如果您只是将锁对象作为模块中的全局值(只要它是模块私有的),它同样可以正常工作。这可能会编译成与上面的代码非常相似的东西——尽管围绕锁定对象和单例存在我从未完全理解的各种微妙之处......

let private loggingLock = obj()

【讨论】:

  • 我不知道静态变量是可能的!
  • @SamuelJ Global let 模块中的绑定被编译为某个隐藏类的静态字段 - F# 语言并不认为它们是“静态的”,因为它们只是 let 绑定,但因为它们'不特定于任何类实例,它们在 .NET 术语中是静态的 :-)
猜你喜欢
  • 1970-01-01
  • 2011-05-06
  • 2021-01-05
  • 1970-01-01
  • 2014-12-22
  • 1970-01-01
  • 1970-01-01
  • 2017-12-05
相关资源
最近更新 更多