从另一个线程访问单例对象

时间:2009-12-22 14:19:24

标签: c# threadpool

我使用

调用服务方法

ThreadPool.QueueUserWorkItem(o => service.Method(arg1, arg2));

服务有对象'loggingService',我使用的是Spring.Net

private readonly ILoggingService loggingService = ObjectBuilder.GetObjectByName("LoggingService");

'LoggingService'类是单例。它将日志信息写入log.txt。

当我尝试在此服务方法中调用loggingService.Info(“test”)时,我得到异常:文件正忙于另一个进程。

如何访问loggingService?

4 个答案:

答案 0 :(得分:1)

你的单身人士显然是每个线程 您将需要某种方式在线程之间传递LoggingService

例如,您可以在原始帖子中设置service.loggingService

或者,您可以配置Spring.Net以使其成为非线程本地单例。

请注意,您的LoggingService必须是线程安全的,否则您将在运行时遇到奇怪的错误。

答案 1 :(得分:0)

在编写一些使用大量线程的客户端应用程序时,我遇到了类似的问题。

基本上,您希望LoggingService保留一个内部队列(其访问权限应通过锁控制),每次调用log方法时,只需将消息附加到此队列。在log方法结束时检查队列当前是否正在写入文件,如果没有,则开始写入。

答案 2 :(得分:0)

public static class SingletonLoggingService
{
    public static ILoggingService LoggingService = ObjectBuilder.GetObjectByName("LoggingService"); 
}


SingletonLoggingService.LoggingService.Info("Test");

答案 3 :(得分:0)

我做到了!

我使用队列和线程:

    internal class LoggingService : ILoggingService {
    private readonly Queue<LogEntry> queue = new Queue<LogEntry>();
    private Thread waiter;

    public LoggingService() {
        waiter = new Thread(AddLogEntry);
        waiter.Start();
    }

    public void Shutdown() {
        try {
            waiter.Abort();
        } catch {}
    }

    public void Error(string s, Exception e) {
        lock (queue) {
            queue.Enqueue(new LogEntry(s, e, LogEntryType.Error));
        }
    }

    public void Warning(string message) {
        lock (queue) {
            queue.Enqueue(new LogEntry(message, LogEntryType.Warning));
        }
    }

    public void Info(string message) {
        lock (queue) {
            queue.Enqueue(new LogEntry(message, LogEntryType.Info));
        }
    }

    private void AddLogEntry(object state) {
        while (true) {
            lock (queue) {
                if (queue.Count > 0) {
                    LogEntry logEntry = queue.Dequeue();
                    switch (logEntry.Type)
                    {
                        case LogEntryType.Error:
                             logWriter.Error(logEntry.Message, logEntry.Exception);
                            break;
                        case LogEntryType.Warning:
                            logWriter.Warning(logEntry.Message);
                            break;
                        case LogEntryType.Info:
                            logWriter.Info(logEntry.Message);
                            break;
                    }
                }
            }
            Thread.Sleep(100);
            if (waiter.ThreadState == ThreadState.Aborted) {
                waiter = null;
                break;
            }
        }
    }
}

我在app结束时调用Shutdown():

        protected override void OnExit(ExitEventArgs e) {
        loggingService.Shutdown();
        base.OnExit(e);
    }