Reputation: 43
I am working on an application that queries servers for its status via WMI, I was asked to make it automatically recurrent and that it can queue the queries to get the statuses of several servers every so often. The problem I am having is that the values that are established when the first timer is created have changed by the time the socond one is (like server name, and query type). This is a portion of the code:
public System.Threading.Timer[] schedquery = new System.Threading.Timer[10];
private void button1_Click(object sender, EventArgs e)
{
schedquery[C3MonitorApp.globalVars.tmrArray] = new System.Threading.Timer(writeLog);
schedValues.schedTurns = 120 / schedValues.schedTimer;
schedquery[C3MonitorApp.globalVars.tmrArray].Change(1000, 0);
C3MonitorApp.globalVars.tmrArray++;
}
public void writeLog(object state)
{
//do queries and write results to file then check if the timer
//has done certain amount of loops and dispose or restart
schedValues.schedTurnCounter++;
if (schedValues.schedTurnCounter == schedValues.schedTurns)
{
this.Dispose();
}
else
{
System.Threading.Timer t = (System.Threading.Timer)state;
t.Change(1000 * 60 * schedValues.schedTimer, 0);
}
}
The write log function obtains the server name and query type from a public class, so I want this values like the server name be stored somehow so the timer runs the callback using the original values instead of the ones used to create the second, third or fourth timer.
Regards.
Upvotes: 0
Views: 76
Reputation: 134005
The state
object passed to the timer is the state
argument you pass to the constructor. I'm a little surprised that your code works at all, considering that your code doesn't pass a state
argument. Meaning that the code in your else
should fail with an invalid cast or null reference exception.
It's difficult to say for sure because your question is a little vague, but I think what you want is to create a state object and pass that in the constructor. For example:
class TimerState
{
public string ServerName { get; set; }
public string QueryType { get; set; }
public int TimerIndex { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
schedValues.schedTurns = 120 / schedValues.schedTimer;
var stateObj = new TimerState
{ ServerName = "foo", QueryType = "bar", TimerIndex = C3MonitorApp.globalVars.tmrArray };
schedquery[C3MonitorApp.globalVars.tmrArray] =
new System.Threading.Timer(writeLog, stateObj, 1000, 0);
C3MonitorApp.globalVars.tmrArray++;
}
And change your writeLog
:
public void writeLog(object state)
{
TimerState stateObj = (TimerState)state;
Timer t = schedquery[stateObj.TimerIndex];
//do queries and write results to file then check if the timer
//has done certain amount of loops and dispose or restart
schedValues.schedTurnCounter++;
if (schedValues.schedTurnCounter == schedValues.schedTurns)
{
t.Dispose();
}
else
{
t.Change(1000 * 60 * schedValues.schedTimer, 0);
}
}
I'm pretty sure you don't want to dispose this
. You want to dispose the timer, as I show here.
I'm likely missing something about the specifics of your application, but the above will give you the general idea.
Upvotes: 1