c# - 如果我使用 Spring AOP 横切关注点 + log4net 进行日志记录,如何结束单例对象队列

标签 c# multithreading log4net spring.net producer-consumer

我有一个应用程序,它使用 Spring.AOP 库来应用代理对象来记录程序执行的操作(我使用 xml 配置)。在我使用 log4net 通过 Spring.AOP(简化类)记录消息之前:

public class CommandLoggingAdvice : IMethodInterceptor
{
    // here I get an instance of log4net
    private ILog _Logger = null;
    protected ILog Logger
    {
        _Logger = LogManager.GetLogger("Logger1");            
    }

    public object Invoke(IMethodInvocation invocation)
    {
        Logger1.Info("Now we enter to method");            
        // here i call the method
        object returnValue = invocation.Proceed();
        Logger1.Info("Now we exit from method");
        return returnValue;
    }
}

但是有一个问题:我需要使用一个消息队列,它应该在独立的线程中工作以将程序负载分配到多个线程

这是一个新的 Spring.AOP 类:

public class CommandLoggingAdvice : IMethodInterceptor
{
    private static ProducerConsumerClass LoggingQueue = ProducerConsumerClass.Instance;    
    public object Invoke(IMethodInvocation invocation)
    {
        LoggingQueue.AddTask("Now we enter to method");            
        // here I call the method
        object returnValue = invocation.Proceed();
        LoggingQueue.AddTask("Now we exit from method");
        return returnValue;
    }
}


/// <summary>
/// ProducerConsumerClass implements: 
/// - SingleTon-object, Producer/Consumer queue (queue is a FIFO BlockingCollection) - I need this class to process all messages, which come from  CommonLoggingAdvice class. The reason is that I need to do it in independent thread (.IsBackground = false) 
/// - This version of Singleton class is threadsafe
/// </summary> 
public sealed class ProducerConsumerClass : IDisposable
{
    // here Iget an instance of log4net
    private ILog _Logger = null;
    protected ILog Logger
    {
        _Logger = LogManager.GetLogger("Logger1");            
    }

    private BlockingCollection<string> tasks = new BlockingCollection<string>();

    private static volatile ProducerConsumerClass _instance;
    private static object locker = new object();        
    Thread worker;

    private ProducerConsumerClass()
    {
        worker = new Thread(Work);
        worker.Name = "Queue thread";
        worker.IsBackground = false;
        worker.Start();
    }

    public static ProducerConsumerClass Instance
    {
        get
        {
            if (_instance == null)       
            {
                lock (locker)
                {
                    if (_instance == null)
                    {
                        _instance = new ProducerConsumerClass();
                    }
                }
            }
            return _instance;
        }
    }

    public void AddTask(string task)
    {
        tasks.Add(task);           
    }
 // now this is unused method
 // I need to call this method somehow at the end of program, but cross-cutting concern doesn't allow to do it straightahead
    public void Dispose()
    {
        tasks.CompleteAdding();
        worker.Join();                        
        tasks.Dispose();
    }

    void Work()
    {
        while (true)
        {
            string task = null;
            if (!tasks.IsCompleted)
            {
                Thread.Sleep(1000);
                task = tasks.Take();
                Logger1.Info(worker.Name + " " + task );   
            }
            else
            {
                return;
            }              
        }
    }
}

所以这个类总是在运行(“工作”线程也是如此); 如果“tasks”为空,- tasks.Take() 强制“worker”线程暂停,直到使用 tasks.Add() 添加内容。 但是当程序的所有功能都结束并且我需要退出程序时 - “任务”为空并且“工作人员”暂停 - 所以我无法退出无限循环=>程序永远不会结束。

只要 Spring.AOP 类是横切的并且它们自动应用,我不知道如何告诉“ worker ”线程(方法 Work() )它应该完成( CompleteAdding() 方法,或 Dispose() )。

你能帮我解决这个问题或者告诉我其他方法来做我需要的吗:

  1. 与 Spring.AOP 的横切关注点用于日志记录
  2. 独立线程中带有队列(或生产者/消费者模式)的单例类的线程安全实现,它与应用程序一样长,甚至更长:直到队列为空。

最佳答案

您可以使用独立线程将您的日志写入队列中。使用 lock解决您关于写入队列的需求。

关于c# - 如果我使用 Spring AOP 横切关注点 + log4net 进行日志记录,如何结束单例对象队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24698785/

相关文章:

c++ - fork() 与 C++ 中的 std::async

c# - 为每个 appender 创建不同的 log4net.ILog 实例

asp.net - 如何关闭 INFO 级别的 NHibernate 日志记录?

c# - 将字节数组从 Oracle RAW 转换为 System.Guid?

c# - COM Interop 未通过接口(interface)检测 .NET 函数

c# - 打开和关闭连接的性能与 commandTimeout

c# - 寻找 OnLog 事件 - log4net

c# - 在泛型集合之间转换

java - Java服务层中的多线程

c# - Windows Phone 8 线程无效的跨线程访问