VB.NET: Определить завершение одного из процессов

Все, что вы хотели знать о программизме, но боялись спросить.
Ответить
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

VB.NET: Определить завершение одного из процессов

Сообщение vg »

Джоб запускает два или три процесса (пакаджа). Если все процессы отработали "нормально", по джоб должен вернуть TRUE. Если хоть бы один из процессов завершается FALSE, то джоб должен прибить уже неинтересные другие процессы и вернуть FALSE.

Джоб (контейнер) создаёт треды пакаджей:

Код: Выделить всё

   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
В конце этого вызова "джоб сигнализирует сам себе" устанавливая AutoResetEvent m_evt.Set()

"Первичный" поток джоба анализирует этот ивент приблизительно так:

Код: Выделить всё

        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
Спасибо.
Аватара пользователя
Earl Grey
Маньяк
Сообщения: 2893
Зарегистрирован: 22 фев 2005, 15:07

Сообщение Earl Grey »

дык если уж подвис, то твое

Код: Выделить всё

        Finally
            setExitCode(rc)
        End Try 
может никогда и не сработать.

похоже тебе надо что-то вроде pinga и/или "I'm still working" репорта прикрутить
Ответить