Hi y'all,
After much research, I finally figured threads out.
Once all the threads finished executing their tasks, the main thread/app which called them also exits. There is nothing you can do to keep them running. I tried using ThreadPool at first. Then abandoned this because:
-No control over order of threads
-Exits main application as soon as one thread starts
-EventHandlers are not triggered unless asynchronous
-Difficult to get status of threads
Then I tried Parallel..For loops and also abandoned this because:
- No guarantee that resource would be available; sometimes freezes while waiting for resources
- Difficult to get status of threads
My solution was to get rid of the batch files and used arrays of Threads. In lieu of batch files, I used the ProcessStartInfo options to redirect output and errors to a text file.
I also used parameterized delegates to get the threads running for each group.
For those who may be interested, here's some code snippets:
Private Sub RunAllModels()
'Create run priority list for all models
Dim allDepths As List(Of PriorityDepth) = Huc8ToPriorityDepth(hucfile) 'hucfile = HUC8_Test.csv
Dim allModels As List(Of PriorityModel) = PriorityModelList(allDepths)
groupList = PriorityStringList(allDepths) 'global variable of 33 priority groups
'Run Priority2 models--------------------------------------------
Console.WriteLine(" Loading Priority2 Models: " & $"{DateTime.Now.ToLongTimeString()}" & vbCrLf)
'Create an array of Threads
Dim array2 As Thread() = New Thread(groupList(1).Count - 1) {}
For i As Integer = 0 To groupList(1).Count - 1
Dim huc2 = groupList(1)(i)
array2(i) = New Threading.Thread(AddressOf PriorityTask2)
array2(i).Name = String.Format("P2Thread{0}", i + 1)
array2(i).Start(huc2)
Next
'Do the rest of priorities here....
:
:
: etc.
End Sub
'------------------------------------------
'Parameterized Thread Delegates here....
Private Sub PriorityTask2(huc As String)
Try
Dim starttime = DateTime.Now
Dim swatexe_path = working_folder & huc & "\SWAT_" & huc & ".exe"
Dim swat_log_path = working_folder & huc & "\SWAT.log"
Dim mysuccess_path = working_folder & huc & "\success.fin"
Dim num As Integer = 2 '!Important!
Dim pi As New ProcessStartInfo
pi.WorkingDirectory = working_folder & huc
pi.FileName = swatexe_path
pi.UseShellExecute = False
pi.ErrorDialog = False
pi.RedirectStandardOutput = True
pi.RedirectStandardError = True
pi.WindowStyle = ProcessWindowStyle.Hidden
process2 = New Process '!Important!
process2 = Process.Start(pi) '!Important!
'-------Read SWAT executable output-------------------------------------
Console.WriteLine(" Reading Priority" & num & " " & huc & " SWAT output. This could take a while...")
Dim output As String = process2.StandardOutput.ReadToEnd() '!Important!
process2.WaitForExit() 'Avoid deadlock '!Important!
'-------Write to SWAT file---------------------------------------
Console.WriteLine(" Writing Priority" & num & " " & huc & " output to SWAT file...")
Dim array() As String = output.Split(vbCrLf)
File.WriteAllLines(swat_log_path, array)
'-----Write any error to console-------------------------------
Dim myStreamReader = process2.StandardError '!Important!
' Read the standard error and write it to console
Console.WriteLine(myStreamReader.ReadLine())
'-------Write Finished times to log file----------------------
WriteToTargetLogFile(mysuccess_path, huc, num, starttime)
Catch ex As Exception
Console.WriteLine(vbCrLf & " Error called from PriorityTask2: " & ex.ToString())
End Try
End Sub
This was a real workout!