我正在编写一个审计文件,该文件在每个用户使用我的应用程序时为应用程序编写应用程序中的多个变量的用户名,时间和旧/更改值。它使用FileStream
和StreamWriter
来访问审核文件。每个用户的所有审核都将写入同一文件。
问题是,当两个用户同时更新此审核文件时,每个变量的“旧值”在用户之间混淆。为什么会这样,你怎么解决这里的并发问题呢?
一些代码,为简洁而缩短......
Dim fs As FileStream
Dim w As StreamWriter
Public Sub WriteAudit(ByVal filename As String, ByVal username As String, ByVal oldAddress As String, ByVal newAddress As String, ByVal oldCity As String, ByVal newCity As String)
Dim now As DateTime = DateTime.Now
Dim audit As String = ""
audit += now + "," + username + "," + oldAddress + "," + newAddress + "," + oldCity + "," + newCity
fs = New FileStream(filename, FileMode.Append)
w = New StreamWriter(fs)
w.WriteLine(audit)
w.Close()
fs.Close()
End Sub
它存在于AuditLogger类中,该类通过实例变量引用(每次访问函数时重新分配)。
答案 0 :(得分:2)
你可以试试这个:
TextWriter tw = TextWriter.Synchronized(File.AppendText(filePath));
File.AppendText()方法返回一个StreamWriter对象,TextWriter.Synchronized()方法包装该对象以创建一个可以像StreamWriter一样使用的线程安全的TextWriter。
答案 1 :(得分:2)
重构应用程序,这样您就不必每次都创建AuditLogger
类的新实例。直接使用singleton pattern或dependency-injection框架在整个应用程序中使用相同的实例。
从那里开始,实现变得更加容易:用lock
语句包围写操作,或者使用罗伯特答案中提到的TextWriter.Synchronized
。
这篇文章可能有用:
答案 2 :(得分:0)
有两种方式:
首先,使用共享数据库而不是文件。即使是简单的访问数据库也可以比磁盘上的文件更优雅地处理多个用户。
其次,您可以为每个用户使用单独的文件吗?也许将它存储在%APPDATA%文件夹中?或者也许在某个地方的网络共享上?