mollensoft

Hello All,

I am trying to figure out a way for many threads in my app to log to a single logfile. Here are the details...

a. I instantiate a client class for each incoming socket connection... service the connection then log the result.

b. I am using a User Selectable Threadpool ranging from 1-10 threads

c. The string being written is very short (about 90 bytes)

Problem is the debugger throws an IO Exception "The process cannot access the file ... because it is being used by another process"

This problem doesnt seem to appear in the "Release" Application, only when in the debugger.

I have tried several methods of reducing the contention for the file but they dont seem to work... I have tried the following to resolve this:

1. I tried using named pipes per the MSDN guidance but it seemed unstable and didnt log everything.

2. I tried creating a Logger Module that would hold all outbound log events in one large string array and then wait until the the thread pool was 1 or 0 to log to the outfile. This worked ok, but I am not comfortable holding this sometimes large array in memory as the user could exit the application and data would be lost.

3. Below is what I am trying now... note the integer decrement when an exceptional condition exists... I was hoping this would reduce the contention but it still throws the debugger error.

Anybody have any suggestions/ideas

Here's my current Solution:

Private Sub SysLogEntry(ByVal entryline As String)

Dim syslogfilename As String = logpath + "SYSLOG-" + DateTime.Today.ToString("yyyyMMdd") + ".log"

Dim Retry As Integer = 5000

Do While Retry > 0

Try

Dim Stream As New FileStream(syslogfilename, FileMode.OpenOrCreate, FileAccess.ReadWrite)

Stream.Seek(0, SeekOrigin.End)

Stream.Write(System.Text.ASCIIEncoding.ASCII.GetBytes(entryline.ToCharArray()), 0, System.Text.ASCIIEncoding.ASCII.GetByteCount(entryline.ToCharArray()))

Stream.Close()

Retry = 0

Catch ex As Exception

Retry -= 1

If Retry = 0 Then

ErrLogEntry("SysLog Write Failed :" + ex.ToString)

End If

End Try

Loop

End Sub



Re: Visual Basic Express Edition Many Threads Logging to Same File(?)

DMan1

The filestream open method has an overloaded method in which you can specify the share mode:

public static System.IO.FileStream Open(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share)

Member of System.IO.File

Summary:

Opens a System.IO.FileStream on the specified path, having the specified mode with read, write, or read/write access and the specified sharing option.

Parameters:

share: A System.IO.FileShare value specifying the type of access other threads have to the file.

mode: A System.IO.FileMode value that specifies whether a file is created if one does not exist, and determines whether the contents of existing files are retained or overwritten.

access: A System.IO.FileAccess value that specifies the operations that can be performed on the file.

path: The file to open.

Try specifing a readwrite share

ReadWrite

Member of System.IO.FileShare

Summary:

Allows subsequent opening of the file for reading or writing. If this flag is not specified, any request to open the file for reading or writing (by this process or another process) will fail until the file is closed. However, even if this flag is specified, additional permissions might still be needed to access the file.






Re: Visual Basic Express Edition Many Threads Logging to Same File(?)

ReneeC

hey dman1

yanno this seems like a really good reason to use a queue or stack.

Threads that need logging just put them on a queue. Another thread monitors the queue and does the I/O






Re: Visual Basic Express Edition Many Threads Logging to Same File(?)

mollensoft

Thanks DMan1, I tried file share mode but I get the same exception... I appreciate your help just the same :>) I guess I will try building a Module that has a large string array that threads can push to then can be emptied when the threadcount gets low.

Below is the Code that Failed:

Private Sub SysLogEntry(ByVal entryline As String)

Dim syslogfilename As String = logpath + "SYSLOG-" + DateTime.Today.ToString("yyyyMMdd") + ".log"

Dim Retry As Integer = 5000

Do While Retry > 0

Try

'Dim Stream As New FileStream(syslogfilename, FileMode.OpenOrCreate, FileAccess.ReadWrite)
Dim Stream As New System.IO.FileStream(syslogfilename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)

Stream.Seek(0, SeekOrigin.End)

Stream.Write(System.Text.ASCIIEncoding.ASCII.GetBytes(entryline.ToCharArray()), 0, System.Text.ASCIIEncoding.ASCII.GetByteCount(entryline.ToCharArray()))

Stream.Close()

Retry = 0

Catch ex As Exception

Retry -= 1

If Retry = 0 Then

ErrLogEntry("SysLog Write Failed :" + ex.ToString)

End If

End Try





Re: Visual Basic Express Edition Many Threads Logging to Same File(?)

mollensoft

Ok, This seems to work (at least one way to do it) I tried it with 20 Threads and it seems to work fine. I check every 10 seconds to see if the thread count is low (<5) and then exec LoggerModule.Flush() and all seems to work well with no contention ({yet}). Thanks to Dman1 and ReneC for helping, (please let me know if you think this is not an efficient way to perform this type of process... :>)

Imports System.IO

Module LoggerModule

Public logqueue As New Queue

Public questat As String

Public Sub flush()

Try

questat = "About To Flush SYSLOG Log Queue"

Dim AppPath As String = Environment.CurrentDirectory()

Dim logpath As String = AppPath + "\logs\"

Dim syslogfilename As String = logpath + "SYSLOG-" + DateTime.Today.ToString("yyyyMMdd") + ".log"

Dim Stream As New System.IO.FileStream(syslogfilename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)

Stream.Seek(0, SeekOrigin.End)

Do While logqueue.Count > 2

Dim logme As String

logme = CType(logqueue.Dequeue, String)

logme = logme + vbCrLf

Stream.Write(System.Text.ASCIIEncoding.ASCII.GetBytes(logme.ToCharArray()), 0, System.Text.ASCIIEncoding.ASCII.GetByteCount(logme.ToCharArray()))

Loop

Stream.Close()

questat = "MTA Log Queue Successfully Flushed"

Catch ex As Exception

ErrLogEntry("LoggerModule Flush Error: " + ex.ToString)

End Try

End Sub

End Module