In my Windows service app I am using timers a lot. I'm using only System.Timers. I've never experienced this problem before, but suddenly I got this exception:
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()
In my method I am stopping the timer, and changing the timer interval. That is the place where I got the exception.
I have read something about this bug but is it still passible to have this bug even in .NET 3.5?
How do I fix it? Should I renew the timer object after stopping and set the interval to a new object? I am using GC.KeepAlive(dataTimer);
Edit: I found some other questions about this problem:
*I found a link http://www.kbalertz.com/kb_842793.aspx Basically as soon as you stop a timer, the internal System.Threading.Timer becomes available for Garbage Collection, sometimes causing the elapsed event not to occur, or sometimes causing a disposed reference exception. Although not described in the article, my solution was to create a new timer every time the timer was to be stopped and re-add the elapsed events. Not efficient but easy, and not a problem processor-wise to me. This has totally solved my problem. Cheers for all who responded.*
But I am confused as to why the bug is still there, and I need to be sure that re-adding the timer is a good idea...
Code that caused the error:
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();
}
Function was called from SerialPortDataReceived event:
private void SerialPortDataReceived(object sender, EventArgs e)
{
StartAsyncResponseTimer();
}
Timer was stopped before calling changing interval.
Timer is private field of my class:
private Timer asyncResponseTimer = new Timer();
EDIT: The application has been running for several months in a row and this is first time I got this exception!
My dispose pattern:
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();
}
}
You may need the . NET Framework 3.5 to run an app on Windows 11, Windows 10, Windows 8.1, and Windows 8. You can also use these instructions for earlier Windows versions.
NET Framework is used to create and run software applications. . NET apps can run on many operating systems, using different implementations of . NET. . NET Framework is used for running .
NET Framework 3.5. 1 is vulnerable to remote code execution attacks.
Can it be that your getting serial port data just after you have disposed your timer? It is the only thing that comes to my mind with the data you have posted!. What are you doing in the Stop()! method inside the Dispose()????
It seems as you start your timer when receiving data on the serial port. What happens if you receive additional data on the port before the timer has finished sending the response? It seems, based on the information you have posted, that the timer interval then will be changed and started (again) while timer still is processing its timer event.
Have you considered the above scenario? Is the timer AutoReset or not? When are you calling Stop()?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With