如何从vb

时间:2016-04-13 07:13:30

标签: vb.net multithreading timer

我有一个在我的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

如果我运行应用程序并且服务器意外断开连接,则目前它不会自动重新连接。但是如果我点击连接按钮(无论如何都调用定时器),它将运行定时器

有人可以帮忙吗?

提前致谢

1 个答案:

答案 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属性并调用StartStop是多余的。 Start已将Enabled设置为TrueStop将其设置为False。做其中一个,而不是两个。当您知道要启动或停止Timer的事实时,最适合调用方法。如果您的Boolean值可能是TrueFalse,那么您应该使用该属性。使用文字值设置属性本身并没有错,但它不是预期的。适用于使用该属性的示例是当您使用相同的方法从辅助线程启动和停止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

同样,在任何线程上调用该方法都可以正常工作。