Доступ к одноэлементному объекту из другого потока - PullRequest
2 голосов
/ 22 декабря 2009

Я вызываю метод обслуживания, используя

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

Сервис имеет объект 'loggingService', который я получил с помощью Spring.Net

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

Класс 'LoggingService' является одноэлементным. Записывает информацию журнала в файл log.txt.

Когда я пытаюсь вызвать loggingService.Info ("test") в этом методе службы, я получаю исключение: файл занят другим процессом.

Как я могу получить доступ к сервису регистрации?

Ответы [ 4 ]

1 голос
/ 22 декабря 2009

Ваш синглтон, по-видимому, на поток.
Вам понадобится какой-то способ передачи LoggingService между потоками.

Например, вы можете установить service.loggingService в исходном потоке.

В качестве альтернативы вы можете настроить Spring.Net, чтобы сделать его не локальным синглом потока.

Обратите внимание, что ваш LoggingService должен быть поточно-ориентированным, иначе вы получите странные ошибки во время выполнения.

0 голосов
/ 23 декабря 2009

Я сделал это!

Я использую очередь и потоки:

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

Я вызываю Shutdown () в конце приложения:

        protected override void OnExit(ExitEventArgs e) {
        loggingService.Shutdown();
        base.OnExit(e);
    }
0 голосов
/ 22 декабря 2009
public static class SingletonLoggingService
{
    public static ILoggingService LoggingService = ObjectBuilder.GetObjectByName("LoggingService"); 
}


SingletonLoggingService.LoggingService.Info("Test");
0 голосов
/ 22 декабря 2009

У меня была похожая проблема при написании клиентского приложения, которое использовало кучу потоков.

По сути, вы хотите, чтобы ваш LoggingService сохранял внутреннюю очередь (доступ которой должен контролироваться с помощью блокировки), и каждый раз, когда вы вызываете метод журнала, вы только добавляете сообщение в эту очередь. В конце метода журнала проверьте, записывается ли очередь в файл, а если нет, начните запись.

...