Share via


Error "Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, .."

Question

Wednesday, October 29, 2014 5:35 PM

My windows service creates a File thread who writes to a file.
Whenever the main program and all its other threads need to write to the file, it adds (enqueue) what it needs to write to the file into a synchronized queue (MessagesSync) inside the File thread.
Then, the file thread dequeues them and writes them out into the file.

The windows service creates thread for myClass.
myClass creates thread for clsProcessor.
clsProcessor calls Sub WriteToFile that puts the string into FileSession synchronized queue.

I had run the program for a long time, but, this morning, I got the error "Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, such as a thread-safe wrapper returned by TextReader's or TextWriter's Synchronized methods. This also applies to classes like StreamWriter and StreamReader.".

Why do I get the error, and how can I fix it ?

Thank you.

These are my codes:
Module modGlobal
Private FileSession As clsFile = Nothing
Private FileThread As Threading.Thread = Nothing

Private mySession As myClass = Nothing
Private myWorkerThread As Threading.Thread = Nothing

FileSession = New clsFile
FileThread = New Threading.Thread(AddressOf FileSession.ThreadMain)
FileSession.sLogFileName = "c:\myFolder\myFile.txt"
FileThread.Name = "FileThread"
FileThread.Priority = Threading.ThreadPriority.Lowest
FileThread.Start()
:
mySession = New myClass
myWorkerThread = New Threading.Thread(AddressOf mySession.ThreadMain)

Friend Sub WriteToFile(ByVal sMsg As String)
    FileSession.WriteLine(sMsg)
End Sub

End Module

'********************************************************************************
Public Class myClass
:
Dim Processor As New clsProcessor
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf Processor.ProcessIt))
:
end class

'********************************************************************************
Public Class clsProcessor
:
WriteToFile("This is my test to write to file")
:
end class

'********************************************************************************

Imports System.Threading
Imports System.IO
Public Class clsFile
    Public sLogFileName As String
    Private swLogOrig As StreamWriter
    Private swLog As TextWriter
    Private Messages As New Queue
    Private MessagesSync As Queue = Queue.Synchronized(Messages)
    Private Terminated As Boolean = False
    Public Sub ThreadMain()
        Dim bError As Boolean
        Dim sPacket As String = ""

        Try
            swLogOrig = New StreamWriter(sLogFileName, True)
            swLog = TextWriter.Synchronized(swLogOrig)
            Do While Not Terminated
                sPacket = ""
                While MessagesSync.Count > 0 And Not (Terminated)
                    bError = False
                    Try
                        sPacket = MessagesSync.Dequeue
                    Catch ex As Exception
                        bError = True
                    End Try
                    If Not bError Then
                        swLog.WriteLine(sPacket)
                    End If
                End While
                Thread.Sleep(1)
            Loop
        Catch ex As Exception
  '>>>>>>>>>>>>>>>>ERROR HERE
 End Try
     :
    end Sub

    Public Sub WriteLine(ByVal Line As String)
         MessagesSync.Enqueue(Line)
    End Sub

end class

All replies (7)

Thursday, October 30, 2014 7:21 AM ✅Answered

Hello,

Based on my understanding, the Textwriter has not been disposed and it will throw this exception, we could use a Using block for both the streamwriter and textwriter.

Regards.

Carl

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Friday, October 31, 2014 3:01 PM ✅Answered

Hi aujong,

Simply setting the reference = Nothing isn't the same as explicitly calling the Dispose method.  It's recommended to call Dispose on anything that implements IDisposable once you're done with it, so that the runtime can release all the unmanaged resources associated with it.


Monday, November 3, 2014 9:34 PM ✅Answered

I thought the Close method calls the Dispose method ?

I do call
swLogOrig.Close()
then
swLogOrig = Nothing

On some implementations of the Stream class it might, but it's never safe to make that assumption.  Best practice is always to explicitly dispose of an IDisposable when you no longer need it.


Thursday, October 30, 2014 4:05 PM

I can dispose it using the following codes, is that correct ?
            If Not (swLogOrig Is Nothing) Then
                swLogOrig.Close()
                swLogOrig = Nothing
            End If
            If Not (swLog Is Nothing) Then
                swLog.Close()
                swLog = Nothing
            End If

I think I know what the problem was.

I accidentaly kept closing and re-opening the file every minute.
Then, when I close and open the file, another part of the code access it at the same time, like swLog.WriteLine(sPacket). I got the error on swLog.WriteLine, I think it was during closing and re-opening the file.

What do you think ?


Friday, October 31, 2014 5:20 AM

I can dispose it using the following codes, is that correct ?
            If Not (swLogOrig Is Nothing) Then
                swLogOrig.Close()
                swLogOrig = Nothing
            End If
            If Not (swLog Is Nothing) Then
                swLog.Close()
                swLog = Nothing
            End If

I think I know what the problem was.

I accidentaly kept closing and re-opening the file every minute.
Then, when I close and open the file, another part of the code access it at the same time, like swLog.WriteLine(sPacket). I got the error on swLog.WriteLine, I think it was during closing and re-opening the file.

What do you think ?

Hi,

I agree with you about the reason but for the code I prefer the way with using blcok, since that will dispose them when there is not any reference to that object, but the one you shared will not dispose since they don't equal to nothing and then that code will not dispose them when you finished using these objects.

Regards.

Carl

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Friday, October 31, 2014 1:59 PM

Hi,
Thank you for your reply.
Actually, it will dispose it because if the swLogOrig is not nothing (which that's the case), then it calls swLogOrig.Close() and then swLogOrig = Nothing.


Monday, November 3, 2014 5:06 PM

I thought the Close method calls the Dispose method ?

I do call
swLogOrig.Close()
then
swLogOrig = Nothing