【问题标题】:How to catch events in multi-threaded application that can be watched by main thread?如何在多线程应用程序中捕获可由主线程监视的事件?
【发布时间】:2009-12-04 23:02:28
【问题描述】:

我有一个控制台应用程序 (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

我目前没有收到任何错误提示,应用程序也没有在主线程中访问预期的处理程序。

【问题讨论】:

    标签: c# vb.net multithreading event-handling


    【解决方案1】:

    我使用静态事件来完成你想要的。

    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);
        }
    
    
    }
    

    【讨论】:

    • C# 很好,我更喜欢它,雇主出于某种原因选择了 VB。让我试试看!
    • 该事件将被引发和处理,虽然它不会在主线程中而是在引发它的线程中处理。
    • @Yann,这很好。 @Chris,那行得通!谢谢。
    【解决方案2】:

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

    您需要将_ErrorLogger 的引用传递给WorkerBase 实例或传递处理程序的地址。由于您在 WorkerBase 中自动创建 EventLogger 的新实例,因此新的 _Log 实例没有连接事件处理程序。请注意,处理程序中可能存在您必须处理的多线程问题。

    【讨论】:

    • 再次,我的遗漏。构造函数传入记录器并将私有对象设置为该实例。
    猜你喜欢
    • 2013-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多