System.Threading.Timer не срабатывает через некоторое время
У меня есть приложение для Windows. И отлаживая его, запустив консольный режим.
Здесь http://support.microsoft.com/kb/842793
написано, что Timers.Timer имеет ошибку и не работает в службах Windows. И обходным путем является использование Threading.Timer
И эта статья предназначена для .NET 1.0 и 1.1
Я использую .NET 4, но через некоторое время Threading.Timer также не запускается. Так что же может быть причиной этого?
И что вы можете предложить в качестве обходного пути?
Спасибо,
С наилучшими пожеланиями
EDIT: я изменил таймер с Threading.Timer на Timers.Timer и работает без проблем.
Ответы
Ответ 1
Сохраняете ли вы ссылку на свой таймер где-нибудь, чтобы предотвратить сбор мусора?
От документы:
Пока вы используете таймер, вы должен содержать ссылку на него. Как и в случае любой управляемый объект, таймер сборку мусора, когда есть нет ссылок на него. Тот факт, что Таймер по-прежнему активен, не предотвращает он не собирается.
Ответ 2
Работать вокруг?
Лично я предлагаю использовать функцию RegisterWaitForSingleObject, а не таймеры для точной причины, в которой вы работаете. RegisterWaitForSingleObject регистрирует делегат, который будет вызываться на интервале, который вы установите аналогично таймеру, и его очень легко реализовать. В течение нескольких часов вы можете иметь тестовую проводку. Я использую этот метод интервальной стрельбы в своих службах Windows, и это надежное и надежное решение, которое работает для меня.
Прочитайте приведенную ниже ссылку и перейдите по ссылкам в статье для образцов кода и прохождений.
Выполнение периодического процесса в .NET с помощью службы Windows:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html
Ответ 3
Ваш объект таймера выходит из области видимости и получает стирание с помощью Garbage Collector через некоторое время, что останавливает обратные вызовы при стрельбе.
Сохраните ссылку на него в члене класса.
Ответ 4
Полный пример службы Windows с использованием корпоративной библиотеки для ведения журнала и повторяющихся потоков. Удалите строки logger.write, если не используете библиотеку entreprise
namespace Example.Name.Space
{
public partial class SmsServices : ServiceBase
{
private static String _state = "";
private ManualResetEvent _stop = new ManualResetEvent(false);
private static RegisteredWaitHandle _registeredWait;
public WindowsServices()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Logger.Write("Starting service", LoggerCategory.Information);
_stop.Reset();
_registeredWait = ThreadPool.RegisterWaitForSingleObject(_stop,
PeriodicProcess, null, 5000, false);
}
protected override void OnStop()
{
// UpdateTimer.Stop();
_stop.Set();
Logger.Write("Stopping service", LoggerCategory.Information);
}
private static void PeriodicProcess(object state, bool timedOut)
{
if (timedOut)
{
// Periodic processing here
Logger.Write("Asserting thread state", LoggerCategory.Debug);
lock (_state)
{
if (_state.Equals("RUNNING"))
{
Logger.Write("Thread already running", LoggerCategory.Debug);
return;
}
Logger.Write("Starting thread", LoggerCategory.Debug);
_state = "RUNNING";
}
Logger.Write("Processing all messages", LoggerCategory.Information);
//Do something
lock (_state)
{
Logger.Write("Stopping thread", LoggerCategory.Debug);
_state = "STOPPED";
}
}
else
// Stop any more events coming along
_registeredWait.Unregister(null);
}
}
}