在我的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