我有一个在我的Windows窗体上调用的计时器功能,当点击UI上的按钮时,该功能可以正常工作。但是,在我的应用程序中,我使用TCP套接字连接到服务器,当服务器断开连接时捕获抛出的异常,此时Id就像定时器启动(自动收报机)然后运行重新连接。 当我从try catch引用计时器时它不会运行,所以我想象它因为它在主线程上?
这是我的计时器代码: Public Delegate Sub DroppedConnectionDelegate(ByVal ReConn As Integer)
Public Sub DroppedConnection(ByVal ReConn As Integer)
Console.Write("Dropped Connection()")
Thread.Sleep(1000)
If ReConn = 1 Then
MakeConnection(My.Settings.savedIP, False)
Else
isRunning = False
Second = 0
'client.Close()
'client.Dispose()
Timer1.Interval = 1000
Timer1.Enabled = True
Timer1.Start() 'Timer starts functioning
End If
' End If
End Sub
Public Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Second = Second + 1
Console.WriteLine(Second)
If Second >= 10 Then
Timer1.Stop() 'Timer stops functioning
Timer1.Enabled = False
MakeConnection(ServerAddressString, False)
End If
End Sub
这是Id喜欢在catch异常上调用计时器的子:
Public Shared Sub ReceiveCallback(ByVal ar As IAsyncResult)
Dim state As StateObject = CType(ar.AsyncState, StateObject)
Dim client As Socket = state.workSocket
Dim strReceiveBuffer As String = String.Empty
' Read data from the remote device.
Dim bytesRead As Integer
Console.WriteLine("ar to string = " & ar.ToString)
'While client.Connected
If (AsynchronousClient.connectDone.WaitOne(5000, True)) Then
Try
If client.Connected = True Then
bytesRead = client.EndReceive(ar)
Console.WriteLine("Socket Connected")
If bytesRead > 0 Then
state.sb.Clear()
' There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead))
strReceiveBuffer = state.sb.ToString()
MainForm.main_Response = state.sb.ToString()
If strReceiveBuffer.IndexOf("doses-remaining") > 0 Then
response = state.sb.ToString()
MainForm.GetLabelTextToString(response)
'receiveDone.Set()
'isReceived = True
'Return
End If
' Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
Else
' All the data has arrived; put it in response.
If state.sb.Length > 1 Then
response = state.sb.ToString()
End If
' Signal that all bytes have been received.
receiveDone.Set()
isReceived = True
End If
Else
MainForm.WriteLog("RecieveCallback() Error outside catch :" & Date.Today.ToString & " " & TimeOfDay)
MainForm.UpdateList("RecievecallBack error, attempting reconnect..." & client.RemoteEndPoint.ToString())
MainForm.isRunning = False
MainForm.DroppedConnection(0)
End If
Catch ex As Exception
'MessageBox.Show("ReceiveCallback Error, Check Log.")
MainForm.WriteLog("RecieveCallback() Error inside catch :" & Date.Today.ToString & " " & TimeOfDay & ex.Message)
MainForm.UpdateList("RecievecallBack error, attempting reconnect..." & client.RemoteEndPoint.ToString())
client.Shutdown(SocketShutdown.Both)
client.Close()
client.Dispose()
MainForm.isRunning = False
Dim d As DroppedConnectionDelegate = AddressOf MainForm.DroppedConnection
'MainForm.DroppedConnection(0)
d.BeginInvoke(0, Nothing, Nothing)
Exit Try
End Try
End If
' End While
End Sub 'ReceiveCallback
如果我运行应用程序并且服务器意外断开连接,则目前它不会自动重新连接。但是如果我点击连接按钮(无论如何都调用定时器),它将运行定时器
有人可以帮忙吗?
提前致谢
答案 0 :(得分:1)
我不是百分百肯定,因为我从未尝试过,但我认为如果您使用Timers.Timer
代替Windows.Forms.Timer
,那么您现在正在做什么将工作。默认情况下,Timers.Timer
将在辅助线程上引发其Elapsed
事件,但您可以将表单或其他控件分配给其SynchronizingObject
属性,以使其在UI线程上引发事件。在这种情况下,从辅助线程调用Start
应该没问题。
如果这不起作用,那么在开始Timer
之前,您可以通过首先将方法调用编组到UI线程来执行您想要的操作。这可能是这样的:
Private Sub StartTimer()
If Me.InvokeRequired Then
Me.Invoke(New Action(AddressOf StartTimer))
Else
Me.Timer1.Start()
End If
End Sub
您可以在任何线程上调用该方法,它就可以正常工作。
请注意,设置Enabled
属性并调用Start
或Stop
是多余的。 Start
已将Enabled
设置为True
,Stop
将其设置为False
。做其中一个,而不是两个。当您知道要启动或停止Timer
的事实时,最适合调用方法。如果您的Boolean
值可能是True
或False
,那么您应该使用该属性。使用文字值设置属性本身并没有错,但它不是预期的。适用于使用该属性的示例是当您使用相同的方法从辅助线程启动和停止Timer
时:
Private Sub EnableTimer(enable As Boolean)
If Me.InvokeRequired Then
Me.Invoke(New Action(Of Boolean)(AddressOf EnableTimer), enable)
Else
Me.Timer1.Enabled = enable
End If
End Sub
同样,在任何线程上调用该方法都可以正常工作。