在我的Windows服务应用程序中,我使用了很多计时器。我只使用System.Timers。 我以前从来没有遇到过这个问题,但突然我得到这个异常:.NET 3.5 C#与System.Timer错误System.ObjectDisposedException:无法访问处置对象
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()
在我的方法,我停止计时器,并改变定时器的时间间隔。那是我得到例外的地方。
我已经读过关于这个bug的一些信息,但是即使在.NET 3.5中也有这个bug吗?
我该如何解决?我应该在停止后更新计时器对象并将间隔设置为新对象吗?我正在使用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();
编辑:行中的应用程序已经运行了数月,这是我第一次得到这个例外!
我的Dispose模式:
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();
}
}
给我们您的代码以及错误消息。我的猜测是你正在使用一个“使用”块,当你不应该完成时,它会自动处理一些东西。我们会看看你的代码,尽量告诉你。 – Chris 2011-01-25 12:59:20
使用计时器时,我的技术的价值在于在某处(例如私人字段或定时器集合)保留对它们的引用,以便我知道仍然有引用。这样,我知道他们不会在我想要之前被GCed。虽然你当然必须确保在完成计时器对象时删除该引用。 – Chris 2011-01-25 13:01:06
我有定时器引用为类的私有成员。 – Simon 2011-01-25 13:07:29