0

I had to write a multithreaded program in vb that can process files in a directory simultaniusly. Th problem is that it runs fine for some hours. Then it suddenly stucks at the "Thread.Sleep(500)" because all the 3 thread isAlive method returns with "true" value, but "StartSub" are ended in all threads...and seems to be not terminating. Is my code wrong or what could be the problem?

Basicaly the program is like the following:

private sub main()
    importThread = New Thread(AddressOf StartSub)
    importThread2 = New Thread(AddressOf StartSub)

    for each file in directory
                While True
                    If importThread.IsAlive And importThread2.IsAlive Then
                        Thread.Sleep(500)
                    Else : Exit While
                    End If
                End While

                If importThread.IsAlive Then
                    importThread2 = New Thread(AddressOf StartSub)
                    importThread2.IsBackground = True
                    importThread2.Start()
                Else
                    importThread = New Thread(AddressOf StartSub)
                    importThread.IsBackground = True
                    importThread.Start()
                End If
    next
End sub

Private Sub StartSub(ByVal tp As Object)
       'Read fileinfo and process it for something
end Sub
user3219009
  • 19
  • 1
  • 6
  • You start 2 new threads for each directory. Instead of trying to use raw threads, I suggest you use Tasks and the TPL. This will allow you to use proper methods instead of threads and objects, combine tasks with `await` and `ContinuteWith` etc. You could also use `Parallel.ForEach` to process each folder in parallel – Panagiotis Kanavos Sep 26 '16 at 08:30
  • Thank you but I'm looking for the problem in my code/ thinking. Why does both thread still alive when its method process already done, and why does it working for hours? understanding the problem helps me getting better at multithreading... – user3219009 Sep 26 '16 at 08:48
  • First, how can anyone know when you don't post the code to `StartSub`? There are obvious problems though, like starting two threads for each folder but only checking for those created in the *last* iteration. Even if you didn't generate ghost threads, your code will always wait for one of the `StartSub` methods to finish. If it doesn't, the loop won't finish. – Panagiotis Kanavos Sep 26 '16 at 08:53
  • If you want to get better at multithreading, check the libraries that were built for exactly this purpose. – Panagiotis Kanavos Sep 26 '16 at 08:54
  • I think StartSub code doesn't matter in this case because its ending fine... I know it because I'm logging its running. You say i start new thread in every folder, but actually I start new thread in every file on folders. But since the last thread allready terminated i should not bother the running. I am missing someting here? – user3219009 Sep 26 '16 at 09:01
  • Which one? You are leaking a lot of threads and only checking *one* of them. Besides, that's just *one* of the things that are hard with raw threads - if you want to know when processing ends you need to use synchronization classes, not check whether a thread is alive or not, eg with events or mutexes. With Tasks, you could write `Task.ContinueWith` to run something after a task finishes, or `Task.WaitAll` to wait for many of them to finish. Are you trying to create a pipeline of tasks to process folders? Check `ActionBlock` – Panagiotis Kanavos Sep 26 '16 at 09:04
  • Task might be solution. Why are you saying that i only check 1 of the thread? "If importThread.IsAlive And importThread2.IsAlive Then" section should check both running threads... – user3219009 Sep 26 '16 at 09:07
  • You have a loop over a lot of folders. For *each* of them, you start a *new* thread. 500 folders, 500 threads. Yet you only store a reference to the threads created by the last iteration, and then block as long as that thread is `Alive`, which is true even if that other thread is sleeping. – Panagiotis Kanavos Sep 26 '16 at 09:14
  • That is whats happening (according to my log): 0. Starting 1st thread 1. main thread checks if either thread isalive...the 2nd is not alive it starts 2nd thread. 2. main thread is wainting for either one of the 2 threads isAlive to be false 3. one of the thread is finished code and terminates 4. main thread detects that 1 thread is notAlive so it starts a new thread on what is finished 5. now there is only 2 thread that is running and the main thread will check both of them on the next iteration... – user3219009 Sep 26 '16 at 09:29
  • So what is that missing? What is that causes the threads to hang after hundreds of files? Should I release the terminated thread resource? If yes then how? – user3219009 Sep 26 '16 at 09:29
  • It seems that the thread handling was good, the garbage collector take carte the thread resources left by the terminated threads. The program stuck was because the thread recovered info from a Form control and sometimes the control on the form was unresponsive and this made the thread hang up. Thank you for the direction advices. – user3219009 Sep 26 '16 at 20:07
  • There's nothing wrong with the garbage collector and the thread handling is wrong. `IsAlive` covers many states. You can't use it to detect whether a thread has completed succesfully or not. As for accessing the form, you *can't* access UI controls from another thread. After .NET 2.0 such an attempt will through an exception – Panagiotis Kanavos Sep 27 '16 at 09:22
  • You are right that i cannot access form controls from another thread an thats why I used Invoke... but still the the application does hang sometimes so i just dont use form control values... – user3219009 Oct 18 '16 at 12:30

1 Answers1

0

It seems that the thread handling was good, the garbage collector take carte the thread resources left by the terminated threads. The program stuck was because the thread recovered info from a Form control and sometimes the control on the form was unresponsive even with invoke. This made the thread hang up.

user3219009
  • 19
  • 1
  • 6