VB.NET: Определить завершение одного из процессов
Добавлено: 22 окт 2006, 20:13
Джоб запускает два или три процесса (пакаджа). Если все процессы отработали "нормально", по джоб должен вернуть TRUE. Если хоть бы один из процессов завершается FALSE, то джоб должен прибить уже неинтересные другие процессы и вернуть FALSE.
Джоб (контейнер) создаёт треды пакаджей:
Далее:
Тред уведомляет джоб о завершении работы, вызывая метод джоба
m_parent.setExitCode(retcode)
Этот метод декрементирует количество рабочих тредов m_count, или устанавливает код возврата в ERROR:В конце этого вызова "джоб сигнализирует сам себе" устанавливая AutoResetEvent m_evt.Set()
"Первичный" поток джоба анализирует этот ивент приблизительно так:
Вроде работает. Как сделать надёжнее, не сильно усложняя?
Здесь надо треду пакаджа гарантировано вызвать setExitCode метод родителя (джоба). Если тред подвис - то всё... Разумеется, может помочь немного искусственное:
Спасибо.
Джоб (контейнер) создаёт треды пакаджей:
Код: Выделить всё
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