Search code examples
vb.netmultithreadingobjectdisposedexception

System.ObjectDisposedException in Multithreaded Application


I am writing a simple program to test out various functions of VB.NET, I will later use this in a much more complex program. The idea is to send a message via the serial port com5. The message will be taken from what is entered in the application's textbox. A background worker (activated when a button labeled "send" is pressed) continuously transmits the message. There is also a label, which does nothing.

Imports System.ComponentModel

Public Class Form1

Dim message

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    message = TextBox1.Text
    If BackgroundWorker1.IsBusy = False Then
        BackgroundWorker1.RunWorkerAsync()
    End If
End Sub

Sub SendSerialData(ByVal data As String)
    ' Send strings to a serial port. 
    Try
        Using com5 As IO.Ports.SerialPort =
        My.Computer.Ports.OpenSerialPort("COM5")
            com5.WriteLine(data)
        End Using
    Catch ioex As System.IO.IOException
        TextBox1.Text = ("COM5 Not Found!")
    End Try
End Sub

Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    While (True)
        SendSerialData(message)
    End While
End Sub
End Class

Originally, I used Application.DoEvents(), but it was slow and I heard it was a bad programming practice. (This, however, had no errors.) So I rewrote the program using a background worker. Now, the program runs fine while running, but when closed, this pops up:

System.ObjectDisposedException was unhandled Message: An unhandled exception of type 'System.ObjectDisposedException' occurred in mscorlib.dll Additional information: Safe handle has been closed

I believe this has something to do with the background worker, because if the program is closed and I have not ran the background worker, the error does not appear. I have tried placing a try-catch inside every sub in the program (including changing the exception type for the catch in SendSerialData to be any exception), to no avail. This is my first post in case of issues feel free to comment.


Solution

  • What you need to do is signal to the BackgroundWorker1_DoWork thread that the program is closing so that it can tidy up properly. This is something that the BackgroundWorker class in the .NET framework already knows how to do.

    You need to do the following:

    • Use a BackgroundWorker to run the task
    • Configure the BackgroundWorker to accept a cancellation request
    • Change the While loop in the background task to check for cancellation
    • On exiting the program request cancellation of the background task and then wait for the thread to complete.

    NB: The MSDN page on BackgroundWorker has an example that does almost exactly what you want.