Таймер внутри WCF Singleton, размещенный в службе Windows (через webHttpBinding), неожиданно умирает

У меня есть служба WCF, размещенная в службе Windows (работает в локальной системе). Я запускаю System.Timer внутри него. Операция o1, которая инициализирует таймер, объявляется через конечную точку http через webHttpBinding. Я включил трассировку для System.ServiceModel и из файла .svcLog проверил продолжительность прослушивания для операции o1. Это показывает, что после работы в течение примерно 20 часов прослушивание в конечной точке http просто останавливается.

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

Есть ли рекомендуемый способ поддерживать прослушиватель и, следовательно, таймер в течение длительного времени? Можем ли мы периодически пинговать операцию o1, чтобы держать ее в памяти?

Кроме того, моя переменная таймера, которую я инициализирую внутри операции o1, является переменной экземпляра, разве эта переменная не должна находиться в памяти (WCF является синглтоном), даже если прослушиватель закрывается??

Спасибо большое.

Выдержки из кода-

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class SchedulerWindows : ISchedulerWindows
{
    ///.........all instance variables.....
    DataTimer timer = null; /**DataTimer wraps a System.Timers timer variable**/
    public List<DataTimer> timersInService = new List<DataTimer>();
    public ISchedulerWindows.o1(string s1, string s2, /*********/)
    {
     //..........//
     timer = new DataTimer();
    }
}

public class DataTimer
    {

        /****Newly introduced System.Threading.Timer, previously I was using        System.Timers.Timer which was dying****/

        public System.Threading.Timer thTimer;
        private static readonly object dbAccessLock = new object();
        private static readonly object thCallbackLock = new object();

        public DataTimer()
        {
        }

        public DataTimer(/************/)
        {            
            TimerCallback timerDelegate = new TimerCallback(this.WorkMethod);
            EventLogLogger l = new EventLogLogger();
            //l.LogMessage("setting up timer ");
            thTimer = new Timer(this.WorkMethod, null, 0, period);
        }
...
}

РЕДАКТИРОВАТЬ: переход на пространство имен System.Threading из пространства имен System.Timers И увеличение временного интервала исправили это для меня. Переменная таймера больше не исчезает.


person user96403    schedule 14.08.2011    source источник


Ответы (2)


Наиболее вероятной причиной вашей проблемы является InstanceContextMode. Если вы хотите, чтобы ваш экземпляр службы всегда находился в памяти, вы должны использовать Single. У вас, вероятно, есть PerSession или PerCall, и это объясняет, почему ваш таймер исчезает. Вы упомянули, что ваш сервис одноэлементный, но симптомы очень подозрительны. Экземпляр службы остается в памяти до тех пор, пока вы не выключите хост.

[ServiceBehavior(
         ConcurrencyMode = ConcurrencyMode.Multiple, 
         InstanceContextMode = InstanceContextMode.Single
)]

Из управления экземплярами WCF:

Служба singleton живет вечно и удаляется только после закрытия хоста. Синглтон создается ровно один раз при создании хоста.

РЕДАКТИРОВАТЬ: вы, вероятно, проверили, что служба Windows все еще работает, когда ваш слушатель перестает слушать, а таймер исчезает. Также имеет смысл проверить, остается ли в памяти сам ServiceHost. Вы также можете поместить некоторые журналы в обработчики событий ServiceHosts «Closing», «Closed» и «Faulted».

РЕДАКТИРОВАТЬ 2: Если ваш таймер исчезает, вам следует посмотреть, как вы его распределяете. Скорее всего, он собирает мусор. Вы должны объявить его как поле экземпляра, доступное из живых объектов. Сделайте его статичным, чтобы быть абсолютно уверенным. Вы делаете это для DataTimer, но неясно, как таймер объявляется и размещается внутри DataTimer. Опубликуйте код, пожалуйста.

РЕДАКТИРОВАТЬ 3: Вы не должны создавать таймеры в операции. Что произойдет, если операция будет вызвана более одного раза? Что происходит со старожилом? Я не вижу, как вы его закрываете/распоряжаетесь. У вас также есть два конструктора для DataTimer. Один из них ничего не делает. Кроме того, у вас есть отдельный список таймеров. Это немного запутанно. Пожалуйста, изолируйте проблему и, возможно, опубликуйте новый код после этого.

person Dmitry    schedule 15.08.2011
comment
Хорошо, я добавлю ведение журнала к этим обработчикам даже и/или также создам небольшой компонент с таймером, который пингует мою службу таймера и поддерживает ее в рабочем состоянии. - person user96403; 17.08.2011
comment
Может быть хорошей идеей выяснить, что вызывает эту проблему, прежде чем добавлять компонент «поддерживать активность». Вы сделаете свою службу менее надежной и зависимой от этого компонента проверки связи. Он тоже может исчезнуть :) - person Dmitry; 17.08.2011
comment
Я вижу вашу точку зрения там. На самом деле после дальнейшего анализа я обнаружил, что синглтон остается в памяти, как задокументировано. Умирает только переменная экземпляра System.Timers.Timer!. Я вижу, что все остальные переменные экземпляра все еще там. Похоже, здесь проблема с таймером. - person user96403; 19.08.2011

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

person Richard Blewett    schedule 15.08.2011