#c# #.net #timer
#c# #.net #таймер
Вопрос:
В настоящее время у меня возникли проблемы с системой.Многопоточность.Таймер при развертывании моей службы Windows на сервере Win2k3. Он отлично работает, отсчитывая каждую секунду (перебор для целей отладки) на моем локальном компьютере, когда я его устанавливаю, но после того, как я установлю его на сервер, служба запускается успешно, а затем никогда не запускает событие таймера один раз. Кто-нибудь сталкивался с ситуацией, подобной этой, раньше? Большинство моих исследований выявили проблемы, которые, по-видимому, были распространены в .NET 1.1 целую вечность назад. Спасибо за ваше время и помощь.
protected override void OnStart(string[] args)
{
int interval = Int32.Parse(ConfigurationManager.AppSettings["SleepTime"]) * 1000;
TimerCallback cb = new TimerCallback(ProcessTimerEvent);
QueueWorker worker = new QueueWorker();
workTimer = new Timer(cb, worker, interval, 1000);
}
private static void ProcessTimerEvent(object obj)
{
if (obj is QueueWorker)
{
QueueWorker qw = (QueueWorker)obj;
qw.doWork();
}
}
class QueueWorker
{
public void doWork()
{
// work happening here
}
}
Обновить:
Я обнаружил, что это как-то связано с пользователем, от имени которого должна запускаться служба. Когда служба запускается как система, потоки работают отлично. Кто-нибудь знает, какие разрешения необходимы пользователю для запуска потоков? Я попытался использовать «Действовать как часть операционной системы» в локальных настройках безопасности, но это просто приводит к запуску службы, а затем к немедленному сбою при входе в систему как добавленный мной пользователь.
Комментарии:
1. Действительно очевидный вопрос: какое значение app.Config для
SleepTime
на сервере? Другой вариант: использоватьSystem.Timers.Timer
вместо этого.2. У меня была система. Таймеры. Таймер, прежде чем я реализовал его таким образом. Я получил такое же поведение на своем сервере, служба запустится, тогда событие таймера никогда не сработает. Затем я прочитал, что сервер Win 2k3 выполняет некоторые забавные операции с потоками, и этот таймер может работать не так, как я ожидал. Значение времени ожидания прямо сейчас составляет 1 секунду для моих целей тестирования. Позже это будет то, что мне нужно, когда я не тестирую.
3. Можете ли вы опубликовать ссылки, касающиеся поведения w2k3? Можете ли вы создать консольное тестовое приложение, чтобы исключить работу службы win? Это также было бы намного проще протестировать
Console.WriteLine
. И, извините, что задаю глупые вопросы,SleepTime
1000 миллисекунд = 1 секунде, верно?4. Вероятно, я мог бы создать консольное тестовое приложение, но я считаю, что проблема с сервером Win2k3 заключалась в том, что с самого начала проблема заключалась в потоковой передаче в службах. И да, 1000 мс = 1 сек.
Ответ №1:
Возможно, таймер срабатывает. Вы можете запустить DebugView на целевой машине:
http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx
Затем вы можете поместить вызовы в свой код, чтобы увидеть, что выполняется следующим образом:
System.Diagnostics.Debug.WriteLine("Beginning of Timer event...");
System.Diagnostics.Debug.WriteLine("End of Timer event");
Комментарии:
1. У меня есть сообщение о событии, которое нужно запустить, когда это произойдет, но я ничего не получаю. Также работа внутри таймера не завершается. Я установил его без таймера, просто запустив часть DoWork (), и он ведет себя так, как я и ожидал, даже записывает в журнал событий, где и должен. Таким образом, это полностью связано с таймерами и потоковой обработкой.
2. Интересно, не имеет ли пользователь, под которым запущена служба, доступа к: ConfigurationManager. Настройки приложений [«Время сна»]? Это не имеет смысла, но вы могли бы жестко закодировать значение вместо его чтения и посмотреть, поможет ли это.
3. @mtgibbs21: я бы также посоветовал убедиться, что
OnStart
метод действительно запускает таймер, как вы ожидаете. Вы должны ввести некоторый код, который выводит сообщение приOnStart
вызове, значениеinterval
, а также приOnStart
завершении. Мне кажется, что таймер не создается.4.
interval
Значение заполняется правильно, и создается экземпляр таймера при запуске от имени моего пользователя. Просто по какой-то причинеOnStart
метод просто завершает весь путь до конца, и поток никогда не запускается по таймеру. Опять же, запуск службы какLocal System
устраняет проблему с тем, что таймер не запускается, но он больше не запускается как требуемый пользователь для выполнения своей работы.5. Я также добавил этого пользователя к локальным администраторам на компьютере, но, похоже, это не помогает.
Ответ №2:
Я могу предложить пару решений:
- Используйте консольное приложение, а не службу Windows. Запустите консольное приложение из планировщика задач.
- Создайте свой собственный класс timer. Используйте свои собственные потоки и переходите в режим ожидания для интервала опроса. После пробуждения выполняйте свою работу. Затем снова переходите в спящий режим.
И для полноты картины, вот некоторые из статей, в которых подробно описывается фактическая ошибка:
- http://support.microsoft.com/?kbid=900822
- http://objectmix.com/dotnet/97213-serious-regression-win2k3-sp1-kills-timers.html
- http://groups.google.com/group/microsoft.public.dotnet.framework.performance/browse_thread/thread/8f4430b6f6efe829/5224d5666844a215?hl=en
- http://groups.google.com/group/microsoft.public.dotnet.framework.clr/browse_thread/thread/72a5528aba714fa/eeee6f6d9601c90b?hl=en
- http://www.windowskb.com/Uwe/Forum.aspx/virtual-pc/5593/System-Threading-Timers-Not-Firing
Комментарии:
1. Это хорошая подборка информации. Я собираюсь пометить это как решение, чтобы люди знали, что их нужно прочитать.
Ответ №3:
Хорошо. Спасибо за все ваши предложения по этому поводу. Я создал очень агрессивную схему ведения журнала, и я считаю, что сервер по какой-то причине отключал мои потоки. Я добавил GC.KeepAlive(workTimer)
и, похоже, решил проблему с тем, что таймер не тикает.
На всякий случай, если кто-то еще столкнется с этой проблемой, мне кажется, что локальная система получает приоритет потока, но другие пользователи потенциально могут уничтожить свои потоки по той или иной причине. Поскольку у меня нет полного доступа к серверу, на котором я это развертываю, я запишу исправление в KeepAlive или команда сервера исправила что-то за моей спиной.
Комментарии:
1. Рад, что вы нашли какой-то способ заставить это работать. Я опубликовал некоторые другие возможные решения, которые могут быть полезны вам (но, возможно, и другим), а могут и не быть полезными. И некоторые статьи, в которых подробно описывается ошибка.