Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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 IfI 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