В моем сервисном приложении Windows я часто использую таймеры.Я использую только System.Timers.Я никогда не сталкивался с этой проблемой раньше, но внезапно я получил это исключение:
System.ObjectDisposedException: Cannot access a disposed object.
at System.Threading.TimerBase.ChangeTimer(UInt32 dueTime, UInt32 period)
at System.Threading.Timer.Change(Int32 dueTime, Int32 period)
at System.Timers.Timer.UpdateTimer()
at System.Timers.Timer.set_Interval(Double value)
at MyApp.MySpace.MySpace2.MyClassWithTimer.MethodChangeTimerInterval()
В моем методе я останавливаю таймер и меняю интервал таймера.Это то место, где я получил исключение.
Я кое-что прочитал об этой ошибке, но все еще можно иметь эту ошибку даже в .NET 3.5?
Как мне ее исправить?Должен ли я обновить объект таймера после остановки и установить интервал для нового объекта?Я использую GC.KeepAlive (dataTimer);
Редактировать: Я нашел еще несколько вопросов по этой проблеме:
* Я нашел ссылку http://www.kbalertz.com/kb_842793.aspxКак правило, как только вы останавливаете таймер, внутренний сборщик System.Threading.Timer становится доступным для сборки мусора, что иногда приводит к тому, что истекшее событие не происходит, а иногда вызывает исключение удаленной ссылки.Хотя это и не описано в статье, моим решением было создание нового таймера каждый раз, когда таймер должен был быть остановлен, и повторное добавление прошедших событий.Не эффективно, но легко и не проблема для меня.Это полностью решило мою проблему.Приветствую всех, кто ответил. *
Но я не понимаю, почему ошибка все еще существует, и я должен быть уверен, что повторное добавление таймера - хорошая идея ...
Код, вызвавший ошибку:
private void StartAsyncResponseTimer()
{
switch (_lastRequestType)
{
case 1:
asyncResponseTimer.Interval = 1000;
break;
case 2:
asyncResponseTimer.Interval = 2000;
break;
case 3:
asyncResponseTimer.Interval = 3000;
break;
default:
asyncResponseTimer.Interval = 10000;
break;
}
asyncResponseTimer.Start();
}
Функция была вызвана из события SerialPortDataReceived:
private void SerialPortDataReceived(object sender, EventArgs e)
{
StartAsyncResponseTimer();
}
Таймер был остановлен перед вызовом изменения интервала.
Таймер является частным полеммоего класса:
private Timer asyncResponseTimer = new Timer();
РЕДАКТИРОВАТЬ: приложение работает в течение нескольких месяцев подряд, и я впервые получаю это исключение!
Мой шаблон удаления:
public class SerialPortCommunication{
...
private void SerialPortDataReceived(object sender, EventArgs e)
{
ReadResponse();
StartAsyncResponseTimer();
}
//used to determine if is recieving response over
private void StartAsyncResponseTimer()
{
switch (_lastRequestType)
{
case 1:
asyncResponseTimer.Interval = 1000;
break;
case 2:
asyncResponseTimer.Interval = 2000;
break;
case 3:
asyncResponseTimer.Interval = 3000;
break;
default:
asyncResponseTimer.Interval = 10000;
break;
}
asyncResponseTimer.Start();
}
public virtual void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
// Dispose managed resources.
}
// Dispose unmanaged resources.
_disposed = true;
Stop();
}
}
~SomeClass()
{
Dispose(false);
}
#endregion
public void Stop()
{
_asyncResponseTimer.Stop();
serialPortManager.ClosePort();
}
}