Could not write in a closed textWriter, but it was opened !

Thibow

Member
Joined
Jul 20, 2012
Messages
9
Programming Experience
Beginner
Hello,
I have made an application that saves data incoming from a serialPort to a *.txt file.
I have basically one button that launchs the whole process.


  • serialPort connection
  • name or select a file to write in
  • create a new streamWriter
  • write a line "first line" to the text file
  • receive all the data and store them in the text file
  • close the stream writer
  • close the serial connection

My application works well when I first launch it. I get the data, save them in the text File, close the streamWriter and disconnect the serial port. The problem comes when I click a second time on the main button, then it should follow the same process a second time, but it seems that the application doesn't want to write to the text file a second time.

Here are the most relevant things :

Public Class Export
    Private _fileName As String
    Private _objStream As System.IO.StreamWriter

   Public Sub Go()
       Main.SaveFileDialog1.ShowDialog() 'name or select a file to write in
        _fileName = Main.SaveFileDialog1.FileName

        'If _fileName <> "" Then process

            _objStream = New System.IO.StreamWriter(_fileName, True) 'create a new streamWriter
'writting in the first line
 _objStream.WriteLine("first Line")
'getting the data
'writing the data to the text file in a loop <-- crash here at the second run
End Sub


I connect the serial port before creating a thread that launch the go function adn close it after.
As I said when I fisrt launch the function everything goes well, when I launch the new thread a second time, I get an error while writing the data to the text file in a loop. But it did go well for the first line writing !

It is an ObjectDisposedException "impossible to write in a closed TextWriter".. any guess to go around this problem ?
Thank you in advance
 
It would help if you showed us the actual code that causes the error because there's obviously something wrong with it but we can only guess at what that might be without seeing the code. I'm guessing that you are using the original StreamWriter rather than the new one. As I said though, that's just a guess.

Also, are you actually using the _fileName and _objStream variables outside the Go method? If not then why are they declared outside the Go method? If you are creating, using and destroying a disposable object like a StreamWriter within the same method then the proper way to do so is like this:
Using writer As New IO.StreamWriter(filePath)
    'Use writer here.
End Using
The Using block declares the variable, defines its own scope and implicitly disposes the object.
 
Thank you for your answer, I tried to simplify my problem as much as I could but if you want the full code, then I'll show it up.
I do use _fileName and _objStream variables outside the Go method. As you said I am probably using the firstly created StreamWriter, even if I am creating a new one.

Public Class Export    Private _fileName As String
    Private _objStream As System.IO.StreamWriter
    Private _radioGPX As Boolean
    Public Event FinishedExporting(ByVal thisThread As System.Threading.Thread)
    Dim theForm As Main = CType(My.Application.OpenForms("Main"), Main)




    Sub New(ByVal RadioGPX As Boolean)
        _radioGPX = RadioGPX
        AddHandler theForm.FinishedReceiving, AddressOf FinishedReceivingEventHandler
    End Sub


    Public Sub Go()


        If _radioGPX = True Then
            Main.SaveFileDialog1.FileName = "file.gpx"
            Main.SaveFileDialog1.Filter = "GPX File (*.gpx)|"
        Else
            Main.SaveFileDialog1.FileName = "file.txt"
            Main.SaveFileDialog1.Filter = "Text File (*.txt)|"
        End If


        Main.SaveFileDialog1.Title = "Save Exported File"
        Main.SaveFileDialog1.ShowDialog()
        _fileName = Main.SaveFileDialog1.FileName


        If (StrComp(_fileName, "") <> 0)) Then


            _objStream = New System.IO.StreamWriter(_fileName, True) '<-------- creating a new StreamWriter


            If _radioGPX = True Then
                prepareTextGPX(True) '<--------- writing the begining of the GPX file, this worked without errors even on the second launch
            End If




            theForm.sendA(Nothing) 'send a "a" and wait for the FinishedReceiving event raised by another thread
            
        Else
            RaiseEvent FinishedExporting(System.Threading.Thread.CurrentThread)
            MsgBox("Please select a valid directory", MsgBoxStyle.Exclamation, "Error")
        End If
    End Sub


    Public Sub writeTXT(ByVal pq As Paquet, ByRef type As String)
        If type = "txt" Then
            _objStream.WriteLine(pq.getPaquet) '<----- this is where I get the error on the second run in a raw
        ElseIf type = "gpx" Then
            _objStream.WriteLine(pq.getPaquetGpx)
        End If
        'MsgBox("Text Appended to the File")
    End Sub


    Public Sub prepareTextGPX(ByVal debut As Boolean)
        If debut Then
            _objStream.WriteLine("<?xml blabal?>") '<-- this worked without errors even on the second launch
        Else
            _objStream.WriteLine(vbTab + vbTab + "</blabla>")
        End If
    End Sub
    Sub FinishedReceivingEventHandler()
        Dim paquetList() As String
        Dim paquet_1 As Paquet


        If theForm._mainString <> Nothing Then
            Dim i As Integer = 0
            paquetList = theForm._mainString.Split(";"c)
            For Each s As String In paquetList
                If (s.Length = 36) Then
                    If (StrComp(s.Substring(18, 18), "ffffffffffffffffff") <> 0) Then
                        paquet_1 = New Paquet(s)
                        If Not paquet_1.getError Then
                            If _radioGPX = True Then
                                writeTXT(paquet_1, "gpx")
                            Else
                                writeTXT(paquet_1, "txt")
                            End If
                            theForm.SetText(vbCrLf + i.ToString + " " + paquet_1.getPaquet)
                            i += 1
                        End If
                    End If
                End If
            Next
        End If


        If _radioGPX = True Then
            prepareTextGPX(False) 'writting the end of the GPX file
        End If


        _objStream.Close() 'closing the stream
        RaiseEvent FinishedExporting(System.Threading.Thread.CurrentThread)
    End Sub

End Class[COLOR=#3E3E3E][/COLOR]


and here is how the go function is executed creating a new thread from the Main:


 Private Sub BtGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtGo.Click
        Connect()


        If SerialPort1.IsOpen Then


            BtGo.Enabled = False
            _mainString = "" 'reset of the receiving string
            Dim Export1 As New Export(RadioGPX.Checked)
            Dim thread1 As New System.Threading.Thread(AddressOf Export1.Go)
            thread1.SetApartmentState(Threading.ApartmentState.STA)
            AddHandler Export1.FinishedExporting, AddressOf FinishedExportingEventHandler
            setSpinnerVisible(True)
            thread1.Start()
        Else
            MsgBox("Serial Port not connected", MsgBoxStyle.Critical, "Error")
        End If
    End Sub[COLOR=#3E3E3E][/COLOR]

 
I'm guessing that you have one thread trying to write to the StreamWriter after another thread has closed it. I'd maybe put a breakpoint on the line(s) that closes the StreamWriter so that you can detect exactly when it's executed and you will likely find that it's not when you expect. Alternatively, put a Debug.WriteLine after every use of the StreamWriter so that you can see the exact sequence of events.
 
Hello,
I have added some debug writelines and tracked what happened. As I said before, there is no way for the stream to be closed before the end of the process I only have one line to close the Stream, and it wasn't called, there must be some kind of trouble with the threads.. but how / why ?

VB.NET:
_filename :C:\Users\Blabla\Desktop\text.gpx
writting prepare
Send A
Le thread '<Sans nom>' (0x17b8) s'est arrêté avec le code 0 (0x0).
Finished Receiving Raised
Finished Receiving
mainstring :00010202040106070457f8e80200f1340200;ce6bb3024ea12e5f0457f8e80200f7340200;ce6bb3024ea12e5f0457f8e80200ff340200;ce6bb3024ea12e5f0457f8e8020008350200;ce6bb3024ea12e5f0457f8e8020010350200;ce6bb3024ea12e5f0457f8e8020041350200;ce6bb3024ea12e5f0457f8e8020049350200;4a6cb3024e3a2e5f0457f8e8020051350200;4d6cb3024e362e5f0457586201005a350200;4d6cb3024e362e5f04575862010062350200;4d6cb3024e362e5f0457586201006a350200;4d6cb3024e362e5f04575862010073350200;4d6cb3024e362e5f045758620100a3350200;ffffffffffffffffffffffffffffffffffff;ffffffffffffffffffffffffffffffffffff;ffffffffffffffffffffffffffffffffffff;ffffffffffffffffffffffffffffffffffff;ffffffffffffffffffffffffffffffffffff;ffffffffffffffffffffffffffffffffffff
Writting
Writting
Writting
...
Writting
Writting
Writting
Writting
writting prepare
closing _objstream
Le thread '<Sans nom>' (0xfb0) s'est arrêté avec le code 0 (0x0).
Le thread '<Sans nom>' (0x1b2c) s'est arrêté avec le code 0 (0x0).
Le thread '<Sans nom>' (0x1200) s'est arrêté avec le code 0 (0x0).
Le thread '<Sans nom>' (0xd94) s'est arrêté avec le code 0 (0x0).
Le thread '<Sans nom>' (0x11e0) s'est arrêté avec le code 0 (0x0).
Le thread '<Sans nom>' (0x12cc) s'est arrêté avec le code 0 (0x0).
Le thread '<Sans nom>' (0x17a8) s'est arrêté avec le code 0 (0x0).
_filename :C:\Users\Blabla\Desktop\test2.gpx <-------------------------------------- launch it a second time
writting prepare<-------------------------------Writes
Send A
Le thread '<Sans nom>' (0x1b48) s'est arrêté avec le code 0 (0x0).
Finished Receiving Raised
Finished Receiving
mainstring :00010202040106070457f8e80200f1340200;ce6bb3024ea12e5f0457f8e80200f7340200;ce6bb3024ea12e5f0457f8e80200ff340200;ce6bb3024ea12e5f0457f8e8020008350200;ce6bb3024ea12e5f0457f8e8020010350200;ce6bb3024ea12e5f0457f8e8020041350200;ce6bb3024ea12e5f0457f8e8020049350200;4a6cb3024e3a2e5f0457f8e8020051350200;4d6cb3024e362e5f0457586201005a350200;4d6cb3024e362e5f04575862010062350200;4d6cb3024e362e5f0457586201006a350200;4d6cb3024e362e5f04575862010073350200;4d6cb3024e362e5f045758620100a3350200;ffffffffffffffffffffffffffffffffffff;ffffffffffffffffffffffffffffffffffff;ffffffffffffffffffffffffffffffffffff;ffffffffffff...
'VB.net 2005 Simple CDC Demo.vshost.exe' (Managé (v4.0.30319)) : 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_fr_b77a5c561934e089\mscorlib.resources.dll' chargé
Une exception de première chance de type 'System.ObjectDisposedException' s'est produite dans mscorlib.dll
 
Last edited:
I have understood that the problem comes from the fact that the thread1 seems not to be closed totaly and the _objStream wants to be reused.. I have no idea how to go around this problem.
I have detected the problem while using the code you gave me
Using writer As New IO.StreamWriter(filePath)

    'Use writer here.

End Using


I did not have the problem again however when I was writing to a file:
- it writes to file1

when I then asked to write in file2 it
- writes in file2
- AND !! writes in file1 !!

This means that the thread1 seems to still be running !! and a new thread1_copy has been opened !
 
Last edited:
Back
Top