Как отлавливать события в многопоточных приложениях, которые можно наблюдать основным потоком? - PullRequest
2 голосов
/ 05 декабря 2009

У меня есть консольное приложение (VB.NET).Когда он запускается, он порождает рабочие потоки, чтобы найти работу в базе данных и выполнить задачу, а затем искать следующую задачу (в основном рабочий процесс).

Проблема, с которой я столкнулся, заключается в том, что у меня есть обработчик событийв основном потоке, который порождает рабочие потоки.Эти работники, если они ошибаются, поднимают событие для публичного делегата.Однако мой главный поток не обнаруживает эти события, и я не могу понять, как это сделать.Мое намерение состоит в том, чтобы сделать все ведение журнала (текст / база данных), оповещения по электронной почте и перезапустить работника, чтобы найти другую задачу, которая не содержит ошибок.(Это будет расширено в подпрограмме LogErrorMessage и т. Д., Пока я просто сохраняю ее простым Console.Writeline, чтобы я мог видеть, запускается ли метод или нет)

Можно ли это сделать?И если так ... что мне не хватает?

Вот код, который я пытаюсь сделать:

Класс регистратора:

Public Delegate Sub LogDelegateError(ByVal Ex As Exception)

Public Class EventLogger
    Public Event EventError As LogDelegateError

    Public Sub New()
    End Sub

    Public Sub LogError(ByVal ex As Exception)
        RaiseEvent EventError(ex)
    End Sub
End Class

Основная тема:

Private WithEvents _ErrorLogger As EventLogger

Public Sub Process()
     _ErrorLogger = New EventLogger
     AddHandler _ErrorLogger.EventError, New LogDelegateError(AddressOf LogErrorMessage)

     [Loop]
     Dim tWorker As Thread = New Thread(AddressOf oWorker.MainProcess)
     tWorker.Priority = WorkerNode.Attributes(SETTING_NAME_PRIORITY).Value
     tWorker.Start()
     [End Loop]

     [In Finally]
     RemoveHandler _ErrorLogger.EventError, New LogDelegateError(AddressOf LogErrorMessage)
End Sub

Private Sub LogErrorMessage(ByVal ex As Exception) Handles _ErrorLogger.EventError
     Console.WriteLine()
     Console.WriteLine("INTERNAL ERROR:")
     Console.WriteLine(ex.ToString())
     Console.WriteLine()
End Sub

WorkerBase:

Private _Log As New EventLogger
Public Sub MainProcess()
     Try
           [SOME WORK]
     Catch ex As Exception
           Me._Log.LogError(ex)
     End Try
End Sub

В настоящее время я не получаю ошибок, что-то не так, ниэто приложение, обрабатывающее ожидаемый обработчик в главном потоке.

Ответы [ 2 ]

1 голос
/ 05 декабря 2009

Я использую статическое событие, чтобы выполнить то, что вы хотите.

Пример кода на C #, извините. Просто не забудьте удалить событие, если вы закончили использовать объект (Main в примере ниже), иначе это вызовет утечку памяти и никогда не соберет мусор.

public class WorkerClass
{
    public static event ProgressInfoEventHandler ProgressInfo;

    private static void OnProgressInfo(string message)
    {
        if (ProgressInfo != null)
            ProgressInfo(new ProgressInfoEventArgs(message));
    }

    private void DoWork()
    {
          OnProgressInfo("Doing some work");
    }

}

Основная или регистрирующая тема / класс:

public class Main
{
   public Main()
   {
        WorkerClass.ProgressInfo += 
             new ProgressInfoEventHandler(WorkerClass_ProgressInfo);
   }

    void WorkerClass_ProgressInfo(ProgressInfoEventArgs e)
    {
        //LogMessage(e.Message);
    }


}
0 голосов
/ 05 декабря 2009

In WorkerBase : Private _Log As **New** EventLogger

Вам необходимо передать ссылку _ErrorLogger на экземпляр WorkerBase или передать адрес обработчика. Поскольку вы автоматически создаете новый экземпляр EventLogger в WorkerBase, новый экземпляр _Log не подключен к обработчику событий. Просто помните, что в обработчике могут возникнуть проблемы с многопоточностью, с которыми вам придется столкнуться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...