.NET 3.5 C # Ошибка с System.Timer System.ObjectDisposedException: Нет доступа к удаленному объекту

В моем служебном приложении 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();
    }
}

6
задан Wayne Koorts 5 February 2011 в 22:41
поделиться