如何正确关闭日志记录线程

时间:2014-10-07 16:33:34

标签: c# .net multithreading application-shutdown

我有一个日志记录类,其中包含一个线程安全队列,一个Thread来为该队列提供服务,一些支持信号和一个bool

private ConcurrentQueue<LogEntry> _logQ;
private Thread _thread;
private volatile bool _running;
private AutoResetEvent _logEntryWaitingSignal;
private ManualResetEvent _shutdownSignal;

构造函数体:

{
    _logEntryWaitingSignal = new AutoResetEvent(false);
    _shutdownSignal = new ManualResetEvent(false);
    _logQ = new ConcurrentQueue<XrayLogEntry>();
    _thread = new Thread(LoggingThread);
    _thread.IsBackground = false;
    _thread.Start();
}

我的主体:

private void LoggingThread()
{
    _running = true;
    LogStore theLog = ...

    // don't exit until all queued entries are written
    while (_running || !_logQ.IsEmpty)
    {
        LogEntry entry;
        int entryCount = 0;
        while (_logQ.TryDequeue(out entry))
        {
            theLog.WriteEntry(entry);
        }
        _logEntryWaitingSignal.WaitOne();
    }
    _shutdownSignal.Set();
}

我有一段关闭代码,将_running布尔值设置为false(队列无法再添加到_running false),然后发出信号要唤醒的线程,然后等待它已经处理了所有等待条目的信号并退出:

_running = false;
try
{
    _logEntryWaitingSignal.Set(); // Wakes the thread
    // Wait for thread to complete
    if(!_shutdownSignal.WaitOne(THREAD_SHUTDOWN_TIMEOUT_MILLISECONDS))
        throw new Exception("Timed out waiting for thread to exit.");
}
catch(Exception ex)
{
    ...
}

我的问题是:我可以确保调用此代码,以便它可以在任何可能的(有序)进程终止下执行吗?

我已经尝试从Dispose执行它,并实现终结器来调用Dispose。只要Dispose被调用,例如来自我的应用程序对话框的FormClosed事件,它就可以正常工作。但是,我不相信终结器可以保证以我想要的方式工作,因为看起来即使拥有记录器对象的线程退出,线程也会在_logEntryWaitingSignal.WaitOne()调用时保持活动状态,并且永不退出。

当然,如果我将它作为后台线程,那么进程将退出,但如果我这样做,我怎样才能确保线程在写入条目的过程中不会被关闭?

0 个答案:

没有答案