The following code is to be viewed as an example/ a simple fix. It doesn't explain the "why". It runs the code in a BackgroundWorker
and uses a Timer
to timeout/abort the worker.
Imports System.Runtime.Remoting
Imports System.ComponentModel
Imports System.Threading.Thread
Public Class Form1
Public Sub New()
Me.InitializeComponent()
Me.bgWorker = New BackgroundWorker()
Me.bgWorker.WorkerSupportsCancellation = True
Me.bgTimer = New System.Windows.Forms.Timer
Me.bgTimer.Interval = 60000 '<-- Timeout after 1 minute.
End Sub
Private Sub Connect(ipAddress As String, portNumber As Integer, db As String)
If (Me.bgWorker.IsBusy) Then
Throw New Exception("Worker is busy.")
End If
Dim [error] As Exception = Nothing
Try
AddHandler Me.bgTimer.Tick, New EventHandler(AddressOf Me.OnTimeout)
AddHandler Me.bgWorker.DoWork, New DoWorkEventHandler(AddressOf Me.OnDoWork)
AddHandler Me.bgWorker.RunWorkerCompleted, New RunWorkerCompletedEventHandler(AddressOf Me.OnWorkCompleted)
Me.bgTimer.Enabled = True
Me.bgWorker.RunWorkerAsync(String.Format("tcp://{0}:{1}/{2}", ipAddress, portNumber, db))
Catch ex As Exception
[error] = ex
Me.bgTimer.Enabled = False
RemoveHandler Me.bgTimer.Tick, New EventHandler(AddressOf Me.OnTimeout)
RemoveHandler Me.bgWorker.DoWork, New DoWorkEventHandler(AddressOf Me.OnDoWork)
RemoveHandler Me.bgWorker.RunWorkerCompleted, New RunWorkerCompletedEventHandler(AddressOf Me.OnWorkCompleted)
End Try
If (Not [error] Is Nothing) Then
Throw [error]
End If
End Sub
Private Sub OnDoWork(sender As Object, e As DoWorkEventArgs)
Me.bgThread = Thread.CurrentThread
Try
e.Result = CType(Activator.GetObject(GetType(TechnicalDatabase.TechnicalDatabaseObject), DirectCast(e.Argument, String)), TechnicalDatabase.TechnicalDatabaseObject)
Catch ex As ThreadAbortException
e.Cancel = True
Thread.ResetAbort()
Catch ex As Exception
Throw ex
End Try
End Sub
Private Sub OnWorkCompleted(sender As Object, e As RunWorkerCompletedEventArgs)
Me.bgTimer.Enabled = False
Me.bgThread = Nothing
RemoveHandler Me.bgTimer.Tick, New EventHandler(AddressOf Me.OnTimeout)
RemoveHandler Me.bgWorker.DoWork, New DoWorkEventHandler(AddressOf Me.OnDoWork)
RemoveHandler Me.bgWorker.RunWorkerCompleted, New RunWorkerCompletedEventHandler(AddressOf Me.OnWorkCompleted)
If (Not e.Error Is Nothing) Then
MessageBox.Show(e.Error.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
ElseIf (e.Cancelled) Then
MessageBox.Show("Worker cancelled.", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Information)
Else
Dim remoteObject As Object = CType(e.Result, TechnicalDatabase.TechnicalDatabaseObject)
MessageBox.Show("Success!", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub
Private Sub OnTimeout(sender As Object, e As EventArgs)
Me.bgTimer.Enabled = False
If (Not Me.bgThread Is Nothing) Then
Me.bgThread.Abort()
End If
End Sub
Private bgWorker As BackgroundWorker
Private bgTimer As System.Windows.Forms.Timer
Private bgThread As Thread
End Class
To connect:
Me.Connect(ServerIPAddress.ToString(), ServerRemotingPort, "TechnicalDatabase")
Source of inspiration: