2012-10-03 2 views
5

Я использую C# с Compact Framework 2, SP2.System.Threading.Timer не запускается?

Операционная система устройства была настроена для запуска моего приложения, назовем приложение «Loader.exe».

Loader - это просто: простая форма, отображающая сообщения о состоянии на протяжении всей загрузки, если это необходимо (условия непрофессионала для сообщения об ошибке и сообщение об исключении или «стартовое приложение [xyz]») и конечный автомат работает в фоновом режиме, пока отображается основная полноэкранная форма.

Так конструктор грузчика форма имеет следующие на очень конец:

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». В конце концов, моя программа зависала над сообщением «Запуск Init Init Thread ...»

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

Мысли?

+0

Что означает «повесить на сообщение»? Не похоже на заявление, где все может застрять. –

+0

Не отлаживайте метки. Найдите System.Diagnostics.Debug.Print() и получите дополнительную информацию. –

+0

@ Хенк Холтерман, терминология неверна. «Программа останавливается, потому что она ничего не запускает, а не потому, что что-то блокирует». Я чувствовал, что «зависание» будет более кратким, хотя я понимаю, что у него есть другая коннотация. Что касается использования Debug.Печать вместо ярлыков: в общем, я согласен, хотя с тех пор, как я не знал до того момента, когда приложение остановилось * или *, если бы у меня был доступ к тому, что было напечатано после его остановки, мне нужно было что-то обновленное на экране. Спасибо за подсказку. –

ответ

6

Моя теория заключается в том, что сборщик мусора собирался до таймера , вызывающий обратный вызов. Это означало бы, если бы таймер был глобальным, и тогда явным образом удалялся, когда я добираюсь до RunStateMachine, что он будет работать отлично ... но я не хочу думать, что я решил его просто найти , это происходит с перерывами в месяц отныне.

Похоже, вы хотите подтвердить, что это ваша проблема. Да, это проблема.

Таймер хранится в локальной переменной, которая никогда больше не используется. Это делает его приемлемым для GC. GC-таймер таймера приводит к завершению, что приводит к отключению таймера.

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

Смежные вопросы