Hi,
I've wrote a class that inherits from IO.Ports.SerialPort namespace. The goal of my custom class is to manage delegates (if needed) so I can get rid of them in my main form. The class works great, but it sometimes deadlock when closing the form, often at line 30 of the SerialPortCT class, or at line 39 of the frmForm1. I've tried framework 2.0 and 3.5SP1 with same result. Can someone have any idea how to close the form without thread issues?
Thanks,
Christian
The class:
Public Class SerialPortCT
Inherits IO.Ports.SerialPort
Private _sync As System.ComponentModel.ISynchronizeInvoke
Public Shadows Event DataReceived As EventHandler(Of System.IO.Ports.SerialDataReceivedEventArgs)
Public Shadows Event ErrorReceived As EventHandler(Of System.IO.Ports.SerialErrorReceivedEventArgs)
Public Shadows Event PinChanged As EventHandler(Of System.IO.Ports.SerialPinChangedEventArgs)
Public Sub New(ByVal sync As System.ComponentModel.ISynchronizeInvoke)
' Parent thread
_sync = sync
End Sub
Private Sub DataReceivedCrossThreadEventHandler(ByVal sender As Object, ByVal e As Object)
RaiseEvent DataReceived(sender, CType(e, IO.Ports.SerialDataReceivedEventArgs))
End Sub
Private Sub SerialPortCT_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles MyBase.DataReceived
If Not _sync Is Nothing AndAlso _sync.InvokeRequired Then ' If source thread require invoking...
Dim AsyncResults As IAsyncResult
AsyncResults = _sync.BeginInvoke(New EventHandler(AddressOf DataReceivedCrossThreadEventHandler), New Object() {sender, e}) ' ...invoke asynchronous delegate with arguments
Dim ReturnValue As Object
ReturnValue = _sync.EndInvoke(AsyncResults) ' ...and wait for UI thread to complete its task
Else ' ...otherwise...
DataReceivedCrossThreadEventHandler(sender, e) ' ...call the delegate directly
End If
End Sub
End Class
The main form:
Public Class frmForm1
Private WithEvents COMPort As SerialPortCT
Private Sub frmForm1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
' Set default UI behavior
ComboBox1.Enabled = False
ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList
Button1.Enabled = False
Button1.Text = "CONNECT"
COMPort = New SerialPortCT(Me)
' Set default settings for the port
COMPort.BaudRate = 9600
COMPort.Parity = IO.Ports.Parity.None
COMPort.DataBits = 8
COMPort.StopBits = IO.Ports.StopBits.One
COMPort.ReceivedBytesThreshold = 1
COMPort.Handshake = IO.Ports.Handshake.None
' Populate the combobox with available serial port
For Each port In IO.Ports.SerialPort.GetPortNames
ComboBox1.Items.Add(port)
Next
If ComboBox1.Items.Count > 0 Then
ComboBox1.SelectedIndex = 0
ComboBox1.Enabled = True
Button1.Enabled = True
End If
End Sub
Private Sub frmForm1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
If COMPort.IsOpen Then
COMPort.Close()
End If
COMPort = Nothing
'System.Environment.Exit(0) ' Still deadlock
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If COMPort.IsOpen Then
COMPort.Close()
ComboBox1.Enabled = True
Button1.Text = "CONNECT"
Else
Try
COMPort.Open()
ComboBox1.Enabled = False
Button1.Text = "DECONNECT"
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End Try
End If
End Sub
Private Sub DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles COMPort.DataReceived
TextBox1.Text &= COMPort.ReadExisting
TextBox1.SelectionStart = TextBox1.TextLength
TextBox1.ScrollToCaret()
End Sub
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
COMPort.PortName = CStr(ComboBox1.SelectedItem)
End Sub
End Class