Джоб (контейнер) создаёт треды пакаджей:
Код: Выделить всё
Dim pkg_thread As CPackageWorkThread = m_packages(i)
Dim hThread As Threading.Thread = New Threading.Thread(AddressOf pkg_thread.threadWorkProcedure)
'
' указывает на самого себя в качестве родителя
'
pkg_thread.Parent = Me
pkg_thread.ThreadHandle = hThread
'
' увеличивает счётчик потоков
'
m_count += 1
Тред уведомляет джоб о завершении работы, вызывая метод джоба
m_parent.setExitCode(retcode)
Этот метод декрементирует количество рабочих тредов m_count, или устанавливает код возврата в ERROR:
Код: Выделить всё
Public Sub setExitCode(ByVal rc As Integer)
If rc = eRetCode.eError Then
Interlocked.Exchange(m_rcode, rc)
Else
Interlocked.Decrement(m_count)
End If
m_evt.Set()
End Sub
"Первичный" поток джоба анализирует этот ивент приблизительно так:
Код: Выделить всё
While (Not Interlocked.Equals(m_count, 0))
' Wait for finishing any thread
m_evt.WaitOne()
If Interlocked.Equals(m_rcode, eRetCode.eError) Then
' One of the threads failed.
' Kill all the threads and return False
Monitor.Enter(m_packages.SyncRoot)
Try
For i As Integer = 0 To m_packages.Count() - 1
Dim pkg_thread As CPackageWorkThread = m_packages(i)
If pkg_thread.ThreadHandle.IsAlive Then
pkg_thread.ThreadHandle.Abort()
End If
Next
Return False
Catch ex As Exception
m_errstr = ex.Message
Return False
Finally
Monitor.Exit(m_packages.SyncRoot)
End Try
End If
End While
Return (m_rcode = eRetCode.eSuccess)
Здесь надо треду пакаджа гарантировано вызвать setExitCode метод родителя (джоба). Если тред подвис - то всё... Разумеется, может помочь немного искусственное:
Код: Выделить всё
Public Overloads Overrides Sub threadWorkProcedure()
Dim rc As CThreadedPackageManager.eRetCode = CThreadedPackageManager.eRetCode.eError
Try
...
...
...
rc = CThreadedPackageManager.eRetCode.eSuccess
Catch ex As Exception
Finally
setExitCode(rc)
End Try
End Sub