Убить ветку событий - PullRequest
       1

Убить ветку событий

0 голосов
/ 09 июня 2011

У меня есть событие таймера, которое срабатывает каждую секунду.Иногда, когда я выхожу из программы (в отладчике VS), он говорит мне, что поток событий пытается получить доступ к объекту, который больше не существует (потому что основной поток закончен).Я пытался отключить событие перед выходом (UpdateTime.aTimer.Enabled = false;).Это сокращает число раз, когда эта проблема возникает, но иногда она возникает, потому что событие срабатывает, прежде чем я могу его отключить.

  1. Это серьезная проблема?Уилл преследует меня, если я не справлюсь с этим?
  2. Если да к вышесказанному, как мне его убить?

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

РЕДАКТИРОВАТЬ: больше контекста.Это Winform.

Кроме того, я явно не создаю поток.Насколько я понимаю, поток автоматически создается для обработки событий.

Создание таймера:

public static void Update(){

    System.Timers.Timer aTimer = new System.Timers.Timer(1000);
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
    aTimer.Enabled = true;

}

Обработчик событий:

private static void OnTimedEvent(object source,ElapsedEventArgs e) {

    Form1obj.updateLabel(String.Format("{0}", DateTime.Now.Second),Label1);

}

Обработчик закрытия программы:

private void Form1_FormClosing(object sender,FormClosingEventArgs e) {

    aTimer.Enabled = false;

}

Ответы [ 3 ]

3 голосов
/ 09 июня 2011

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

Как решить эту проблему, зависит от того, как вы настраиваете потоки («поток событий» не дает достаточноинформация о механике).Одним из простых способов может быть задержка основного потока на некоторое время, когда приложение завершает работу, пока не вернутся все потоки.Вы также должны прекратить выпуск новых потоков в течение этого времени.

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

Краткий ответ: никто не сможет дать вам твердый ответ "это исправит вашу проблему" без некоторого контекста того, что вы делаетев вашем коде.

ДОБАВЛЕНО:

Есть несколько «быстрых, плохих и грязных» способов справиться с этим.У меня нет времени на полный анализ, поэтому посмотрите, работают ли они.

  1. Просто исправьте ошибку, подождав
  2. Добавьте счетчик и дождитесь увеличения до

Первое, что я хотел бы рассмотреть, - это добавить сеть безопасности, чтобы не обновлять метку в состоянии отключения.Это независимо от чего-либо еще, поскольку именно здесь ваши ошибки запускаются.Я не думаю, что «основной поток отсутствует» является ядром проблемы, а скорее эта строка:

Form1obj.updateLabel(String.Format("{0}", DateTime.Now.Second),Label1); 

Как вы можете обновить то, что больше не существует?Да, это в главном потоке, так что технически ...

Простое ожидание будет выглядеть примерно так:

private void Form1_FormClosing(object sender,FormClosingEventArgs e) 
{
     aTimer.Enabled = false;  
     Thread.Sleep(5000);
} 

Скрытие формы тоже неплохая идея, поэтому пользовательне видит этого?

Если вы хотите использовать более "COM-подобный подход", вы можете добавить счетчик.Инкремент на Update () (при возникновении события) и декремент OnTimedEvent ().Убедитесь, что вы заблокировали счетчик при его изменении, чтобы не было двух потоков, изменяющих его в одну и ту же миллисекунду.Затем вы можете подождать, пока счетчик не станет равным 0, чтобы завершить закрытие формы или выгрузку приложения.

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

1 голос
/ 09 июня 2011

Вы можете закрыть окно , как указано в MSDN - когда вы устанавливаете таймер на отключение во время обработки выключения, установите флаг, который ваш обработчик событий Elapsed может проверить, чтобы знать, что больше нет работыrequired.

Истекшие события могут возникать после вызова метода Dispose или Stop или после того, как для свойства Enabled установлено значение false, поскольку сигнал для вызова события Elapsed всегда ставится в очередь для выполнения напоток пула потоков.Один из способов разрешения этого состояния гонки - установить флаг, который указывает обработчику событий для события Elapsed игнорировать последующие события.

0 голосов
/ 09 июня 2011

Трудно дать общий ответ на вопрос, серьезен он или нет, все зависит от того, что делает таймер.что это за таймер?система. Как читать один или один из таймеров пользовательского интерфейса?

Если возможно, попытайтесь изменить код, чтобы вы могли сказать таймеру прекратить срабатывание, хотя бы по той причине, чтобы не путать пользователей с сообщением об ошибке.,это может быть так же просто, как разделение переменной или (предпочтительно) использование CancellationToken

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...