Question

I want to write some stats to a text file every time a person loads a page. But every once in awhile I am getting at 'Could Not Open File, Already in use' type of error. I can not 100% replicate this error it is very erratic. My code is

Public Sub WriteStats(ByVal ad_id As Integer)
    Dim ad_date As String = Now.Year & Now.Month

    Dim FILENAME As String = Server.MapPath("text/BoxedAds.txt")
    Dim objStreamWriter As StreamWriter
    objStreamWriter = File.AppendText(FILENAME)
    objStreamWriter.WriteLine(ad_id & ";" & ad_date)
    objStreamWriter.Close()
End Sub

My question is, how can I lock and unlock the file so I stop getting the erratic errors?

Thanks

Was it helpful?

Solution

You will have to handle the exception and build some handling to re-try writing to the file after a short random interval.

If you get too much contention then it might make more sense to log it to a table in a database and create a process to export to a file (if its still needed)

OTHER TIPS

If two or more requests hit your web server at roughly the same time, they will all try to open the same file. You will need to create unique file names for each request.

Public Sub WriteStats(ByVal ad_id As Integer)
    Dim ad_date As String = Now.Year & Now.Month
    Dim FILENAME As String = Server.MapPath("text/BoxedAds.txt")
    Dim index As Integer

    Using fs As New IO.FileStream(FILENAME, IO.FileMode.Append, IO.FileAccess.Write, IO.FileShare.ReadWrite), _
          tl As New TextWriterTraceListener(fs)

        index = Trace.Listeners.Add(tl)
        Trace.WriteLine(ad_id & ";" & ad_date)
        Trace.Listeners(index).Flush()
        Trace.Flush()
    End Using
    Trace.Listeners.RemoveAt(index)
End Sub

Three important things here:

  1. Use of IO.FileShare.ReadWrite to allow multiple writers on the file at once.
  2. The Using statement to make sure the stream is closed immediately, even if an exception occurs. This will minimize collisions
  3. The TextWriterTraceListener will create a temp file for your if it can't open the file you request, to make sure the message isn't lost.

I haven't had any trouble with short info using: File.AppendAllText(path, info);

Regarding the comment on it causing locks, from reflector it uses the same options explained very well by Joel. It does not use the trace writer, so it won't output to a temp file in the case of high load / large content causing trouble.

If the info is large, you really want separate files. For high load, I would go with Joel's suggestion and create a temp file, which can be alternatively done by catching the exception on File.AppendAllText, and using the same File.AppeandAllText with a unique filename.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top