1

So the purpose of it is to check the connection of the ftp server and if the ftp is up then enable timer1. I've read that threads don't work as synchonized and that is causing the problem. Without the thread it works fine, but the program hangs and stops responding constantly.

How can i activate a timer from another thread? Maybe invoking and delegating would work? But i don't know how to do that.

Public Function CanPortOpen(ByVal HostName As String, ByVal Port As Integer) As Boolean
    Dim TCP As New System.Net.Sockets.TcpClient
    Try
        TCP.Connect(HostName, Port)
    Catch
    End Try
    If TCP.Connected = True Then
        CanPortOpen = True
        TCP.Close()
        Timer1.Enabled = True
    Else
        CanPortOpen = False
        TCP.Close()
        Timer1.Enabled = False
        FTPup.Abort()
    End If
End Function

Public Sub CheckConnection()
    CanPortOpen("HostName", Port)
End Sub

Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
    TestFTP = New System.Threading.Thread(AddressOf CheckConnection)
    TestFTP.IsBackground = True
    TestFTP.Priority = Threading.ThreadPriority.AboveNormal
    TestFTP.Start()
End Sub

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    FTPup = New System.Threading.Thread(AddressOf UploadToFTP)
    FTPup.IsBackground = True
    FTPup.Priority = Threading.ThreadPriority.AboveNormal
    FTPup.Start()
End Sub
Janno
  • 149
  • 1
  • 3
  • 13
  • Why do you want all these timers here at all? Do you need a delay time between checking that the TCP connection can be opened and starting the upload? Why all these different threads? Why not just start a thread that does the upload and reports progress, success, or failure? – J... Aug 07 '13 at 22:14
  • @J... Yes the timers are for the purpose of delay. If both of them are in the same thread that would mean i can't change the intervals? Although i am still learning all the things, so maybe it isn't the best approach. – Janno Aug 07 '13 at 22:18
  • ...so you want to check that a connection can be made and then start an upload after waiting a while? I find this a strange circumstance. A thread can sleep, in any case, if you need it to wait a while. There is no reason, however, why a TCP connection needs a rest before you can open it again. – J... Aug 07 '13 at 22:21
  • @J... The reason i am using TCP and timers right now is to prevent the case where it wouldn't connect to the ftp and upload files anymore when the server had been down even for a minute (for example: server restart). So when i restarted the thread, it started working properly again. – Janno Aug 07 '13 at 22:30
  • Still, there are more effective error handling options available. I would also caution against making your threads `AboveNormal` priority - unless you have a really good reason to do so it can cause you a lot of grief. In this case I can't see why your thread would need to have an elevated priority. – J... Aug 07 '13 at 22:49
  • What does the thread priority actually do? I got it from here: http://stackoverflow.com/questions/17867358/textbox-doesnt-get-updated-while-threading/17868545#17868545 When i first started looking into and using threads. – Janno Aug 07 '13 at 22:57
  • A thread's priority determines how time slices are allocated to it by the OS's thread scheduler. Putting too much priority on something that doesn't need it can hurt other threads that actually do. Sometimes, even, lowering priority can be detrimental... it's a big topic. You can start here and google for more : http://en.wikipedia.org/wiki/Priority_inversion – J... Aug 07 '13 at 23:02

1 Answers1

1

I think before you start getting in too deep with threads you should start by looking at the BackgroundWorker component. You can find it on your toolbar in the designer and can drop it on your form. It gives you several events

DoWork - hook up this event with whatever you want done in a background thread

RunWorkerCompleted - hook up this event to run code in the main (UI) thread, triggered when the thread completes. Code here can interact with UI objects as normal.

There are other events that allow you to report progress to your main thread, etc. The purpose of the BackgroundWorker component is to make simple multithreading tasks like this easier.

Documentation is -> here

See -> here for examples of how to pass data from the worker thread to the main thread using EventArgs.


Alternatively, if you just want to run the timer from your thread you can do it like this :

 'Declare an appropriate delegate
 Delegate Sub dlgTimerEnable(ByVal enable as Boolean)
 'the delegate should match the method signature
 Private Sub TimerEnable(ByVal enable as Boolean)
     Timer1.Enabled = enable
 End Sub

and then in your thread procedure

Public Function CanPortOpen(ByVal HostName As String, ByVal Port As Integer) As Boolean
    Dim TCP As New System.Net.Sockets.TcpClient
    Try
        TCP.Connect(HostName, Port)
    Catch
    End Try
    If TCP.Connected = True Then
        CanPortOpen = True
        TCP.Close()
        Me.Invoke(New dlgTimerEnable(AddressOf TimerEnable), New Object() {True})
    Else
        CanPortOpen = False
        TCP.Close()
        Me.Invoke(New dlgTimerEnable(AddressOf TimerEnable), New Object() {False})
        FTPup.Abort()
    End If
End Function

Here Invoke causes the method to be executed on the thread that owns Timer1 (assuming this is a method in your form where Me would refer to your form). The arguments are passed as an object.

You can even do this as a general way to work with any timer, for example :

Delegate Sub dlgTimerEnable(ByRef tmr As Timer, ByVal enable As Boolean)

Private Sub TimerEnable(ByRef tmr As Timer, ByVal enable As Boolean)
    tmr.Enabled = enable
End Sub

and then :

Me.Invoke(New dlgTimerEnable(AddressOf TimerEnable), New Object() {Timer1, True})

This makes your delegate general - you can pass it any timer and enable/disable it.

Community
  • 1
  • 1
J...
  • 30,968
  • 6
  • 66
  • 143
  • I will look into the background worker, but for now about the alternative: it says that 'Invoke' is not a member of 'System.Windows.Forms.Timer. This is probably a noob mistake but still.. – Janno Aug 07 '13 at 22:54
  • @rip2444 sorry, I'd just fixed that - I typed it up in a hurry and forgot that `Timer` isn't a control. The code above should work. – J... Aug 07 '13 at 22:55
  • Just tested, the alternative worked fine, definitely going to look into the BackGroundWorker component aswell. Thank you for your help! – Janno Aug 07 '13 at 23:04