System.Threading.Timer не запускается?
Я использую C# с Compact Framework 2, SP2.
ОС устройства была настроена для запуска с моим приложением, давайте назовем приложение "Loader.exe".
Загрузчик - это просто: единая, простая форма, которая показывает сообщения о состоянии во время загрузки, если это необходимо (условия обывателя для сообщения об ошибке и сообщении об исключении, или "запуск приложения [xyz]"), и конечный автомат, работающий в фоновом режиме в то время как основная полноэкранная форма показана.
Итак, конструктор формы Loader имеет в самом конце следующее:
try
{
label1.Text = "Starting GUI Init Thread..."; //debug only message
System.Threading.Timer guiInit = new System.Threading.Timer(
RunStateMachine, null, 2000, System.Threading.Timeout.Infinite
);
//callback: RunStateMachine, null argument
//initial callback is 2000ms from this point, and doesn't run again.
}
catch (Exception ex1)
{
label1.Text = "GUI Init Error 2";
Failure_Label.Text = ex1.Message;
}
И "RunStateMachine" работает в потоке, отличном от пользовательского интерфейса, позволяя отображать форму, и в любое время, когда RunStateMachine должен взаимодействовать с формой, например, обновлять сообщения, я вызываю функцию, которая использует if(this.InvokeRequired){this.Invoke(...);} else{...}
Итак, моя проблема?
Периодически моя программа зависает, и это потому, что таймер не вызвал обратный вызов. Я добавил в отладочное сообщение в блоке try выше, наряду с МНОГИМИ другими местами, чтобы сказать мне, где он завис, включая сообщение при ОЧЕНЬ старте "RunStateMachine". В конце концов, моя программа зависла на сообщении "Запуск GUI Init Thread..."
Это говорит мне, что таймер потока не работает один раз, когда мне это нужно.
Моя теория состоит в том, что это мусор перед таймером, вызывающим обратный вызов. Это означало бы, что если бы таймер был глобальным, а затем был явно настроен, когда я доберусь до RunStateMachine, он будет работать идеально... но я не хочу думать, что решил его, просто чтобы он периодически появлялся через месяц.
Мысли?
1 ответ
Моя теория состоит в том, что это мусор перед таймером, вызывающим обратный вызов. Это означало бы, что если бы таймер был глобальным, а затем был явно настроен, когда я доберусь до RunStateMachine, он будет работать идеально... но я не хочу думать, что решил его, просто чтобы он периодически появлялся через месяц.
Похоже, вы хотите подтверждение, что это ваша проблема. Да, это проблема.
Таймер хранится в локальной переменной, которая никогда больше не используется. Это делает его подходящим для GC. GC'ing таймера приводит к завершению, что приводит к отключению таймера.
Я предлагаю вам сохранить таймер в поле экземпляра вашего класса формы и удалить его оттуда после срабатывания обратного вызова.