当主线程在C#中停止时,有没有办法获得通知

时间:2014-07-17 12:23:30

标签: c# multithreading spring-aop spring.net thread-synchronization

我正在编写一个使用单独线程进行日志记录的应用程序。 我想在主线程停止时停止单独的线程。但是我无法确定何时完全停止记录器线程,因为我不知道主线程何时停止。 C#中是否有一种机制可以在主线程停止时发送通知? (或者你能想到我的问题的另一种解决方案吗?)

// This class automatically applies on each call of every method of Main() function
public class CommandLoggingAdvice : IMethodInterceptor
{
    private static ProducerConsumerClass LoggingQueue = ProducerConsumerClass.Instance;    
                LoggingQueue.AddTask("Logging message on call of *method*");            
}

public sealed class ProducerConsumerClass
{
    // 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;     
    Thread worker;
    private Thread mainthread;

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

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

    public void AddTask(string task)
    {
        tasks.Add(task);           
    }


    void Work(object mainthread)
    {
        Thread ma = (Thread) mainthread;
        if(ma.ThreadState != ThreadState.Stopped)
        {
             tasks.CompleteAdding();
        }
        while (true)
        {
            string task = null;
            if (!tasks.IsCompleted)
            {
                task = tasks.Take();
                Logger1.Info(task);   
            }
            else
            {
                return;
            }              
        }
    }
}

如果BlockingCollection为空且应用程序仍在工作,则循环调用另一个Take()和结果:logger线程现在暂停。所以当主线程.Threadstate ==停止时,我需要杀死记录器线程

有关问题的更多信息已添加到评论中

1 个答案:

答案 0 :(得分:2)

如果BlockingCollection为空且标记为已完成,则您已在该线程中有代码退出。您的循环检查IsCompleted并退出。

您需要的是主线程在集合上调用CompleteAdding的某种方式。我建议您在ProducerConsumerClass中使用公开方法:

public void AllDone()
{
    tasks.CompleteAdding();
}

因此主线程在完成处理后可以调用AllDone。然后,您的线程将清空队列并退出。

顺便说一下,编写日志循环的更简洁方法是:

foreach (string task in tasks.GetConsumingEnumerable())
{
    Logger1.Info(task);
}

这也使得将来更容易添加取消支持。