2016-04-13 146 views
0

我有一個計時器函數,它在我的Windows窗體上調用,當點擊UI上的一個按鈕時,它可以完美工作。但是,在我的應用程序中,我使用TCP套接字連接到服務器,當服務器斷開連接時,我會捕獲拋出的異常,並且在此時刻讓定時器啓動(ticker),然後運行重新連接。 當我從try catch中引用計時器時,它不會運行,所以我想象它是因爲它在主線程上?如何從另一個線程在主線程上調用函數vb

這裏是我的計時器代碼: 公共委託子DroppedConnectionDelegate(BYVAL RECONN爲整數)

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 

這裏是從那裏我還想呼籲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

您正在使用的Timer類不是線程安全的,在工作線程上調用它的Start()方法並沒有達到您希望的效果。它永遠不會打勾。在這段代碼中使用MainForm也是不正確的,你永遠不會看到任何東西。 –

回答

1

我敢肯定不是100%,因爲我從來沒有試過,但我認爲,如果你使用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 

再次呼籲任何線程方法只是工作。

相關問題