Let me start from saying that it's more a question than a problem that needs to be solved. I have the solution now and things work fine for me. But I wonder why problem occured first time.
This is the code I have right now and it works like I expect:
private void OnNewGameStarted(Game game)
{
_activeGames.Add(game);
TimeSpan delay = game.GetTimeLeft();
var timer = new Timer(delay.TotalMilliseconds) {AutoReset = false};
timer.Elapsed += (sender, args) => GameEndedCallback(game);
timer.Start();
}
private void GameEndedCallback(Game game)
{
if (_statisticsManager.RegisterGame(game))
_gamesRepository.Save(game);
_gameStatusSubscriber.GameStatusChanged(game);
}
I used to use System.Threading.Timer instead of System.Timers.Timer and sometimes timer event (GameEndedCallback method) fired and sometimes not. I couldn't find any reason why it was that way.
This is the code I used to initilize timer (other parts are the same):
TimeSpan delay = game.GetTimeLeft();
new Timer(GameEndedCallback,game,(int)delay.TotalMilliseconds,Timeout.Infinite);
}
private void GameEndedCallback(object state)
{
var game = (Game) state;
Method OnNewGameStarted is event handler and it is called after chain of methods from Fleck webserver when some certain message comes to it.
There is a post about the 3 timer types and what they do.
the main things are:
System.Timers.Timer is for multithreading work
System.Windows.Forms.Timer - from the application UI thread
System.Threading.Timer - not always thread safe!
Timeout.Infinite is The time interval between invocations of callback, in milliseconds. Specify Timeout.Infinite to disable periodic signaling. See MSDN: http://msdn.microsoft.com/en-us/library/2x96zfy7.aspx
Timeout.Infinite is a constant used to specify an infinite waiting period.
Try this to get perodic calls to the callback
new System.Threading.Timer(GameEndedCallback, game, (int)delay.TotalMilliseconds, (int)delay.TotalMilliseconds);
Related
In relation to a previous question of mine ([question] : Which thread will timer method run in? ), I've added a Timer to my Windows Forms app to run every 100ms to show how long the program session has been running. I've defined it as follows (these are only the snippets relevant to the timer):
private System.Timers.Timer timerPureTime = new System.Timers.Timer(100);
timerPureTime.Elapsed += new System.Timers.ElapsedEventHandler(updateTimeElapsed);
this.timerPureTime.SynchronizingObject = currentForm; //where currentForm is my main Form
public void updateTimeElapsed(object sender, ElapsedEventArgs e)
{
if (currentForm.lblTimeElapsed.InvokeRequired) //lblTimeElapsed is your standard Windows Form label
{
currentForm.lblTimeElapsed.Invoke((MethodInvoker)delegate //also, trying to make make GUI invoking thread-safe here
{
TimeSpan t = TimeSpan.FromSeconds(purelyTime);
string showTime = string.Format("{0:D2} min {1:D2} sec",
t.Minutes,
t.Seconds);
currentForm.lblTimeElapsed.Text = showTime;
});
}
else
{
TimeSpan t = TimeSpan.FromSeconds(purelyTime);
string showTime = string.Format("{0:D2} min {1:D2} sec",
t.Minutes,
t.Seconds);
currentForm.lblTimeElapsed.Text = showTime;
}
purelyTime += 0.1;
}
As I understand it the Timer should be running in a thread of its own (taken from the Threadpool) however it still experiences some delay every now and then, throwing the timer off-course. Other threads within the application run pretty regularly (every 250ms) and computation-intensive, but shouldn't these be independent of Timer threads?
What could be the possible causes for timer lag in such cases?
Windows cannot guarantee a precisely regular callback for a timer, so you will definitely see that kind of variance.
You need to take a different approach:
Initialise a Stopwatch field in your class.
Call Stopwatch.Restart() when you want to reset the timing.
Inside updateTimeElapsed() use Stopwatch.Elapsed instead of purelyTime.
Note that your code is completely ignoring the amount of time spent in the timer handler function itself. Inside the handler, you are using Invoke to send a message to the UI and waiting for it to return. That can take an arbitrary amount of time, particularly if the UI is busy.
Regarding C# multithreading and events;
I'm trying to set up a System.Threading.Timer that triggers an AutoReset event. When the event is signalled, the code will perform a task that might take longer than the next timer tick.
In C++, when timers set autoreset events, if the event is already set, effectively nothing happens, and you just miss that particular tick. It works well, the thread can tick away setting an event that is already set, and there are no problems.
In C#, the setting of the event is queued up, either on multiple pool threads, or serially on the timer thread. I have got the timer to callback to one thread but
I cannot for the life of me remember how I did that, I found it on StackOverflow, naturally.
It seems that the callback of the timer blocks until the AutoReset event is reset.
I cannot query the event to see if it is already set.
How can I get the system to ignore this? If I am debugging one thread in the app and hold that thread up, the ticks back up and I get either thread exhaustion or database connection exhaustion, either of which kills the app off.
I have seen that I can use a System.Timers.Timer instead, but this requires a synchronizing object. I know that I have to implement a synchronizing object, but I cannot figure it out. I have found the specification of the interface, I seem to need a delegate function. On numerous responses I see people suggesting you just create a dummy synchronization object, but it's that stage that I am stumbling on.
I feel like I am chasing my tail needlessly just to get the system to ignore timer ticks. I have tried using bool flags to signal when threads are busy, but this seems like an ugly kludge. An example ISynchronizeInvoke implementation would be really helpful.
Thanks in advance for any help you can give with this.
What you're describing can't happen. AutoResetEvent.Set does not block if the event is already set, as this code clearly shows:
private System.Threading.Timer _myTimer;
private AutoResetEvent _myEvent = new AutoResetEvent(false);
private void DoIt()
{
_myTimer = new Timer(MyTimerCallback, null, 1000, 1000);
Console.WriteLine("Press Enter when done");
Console.ReadLine();
_myTimer.Dispose();
}
private void MyTimerCallback(object state)
{
_myEvent.Set();
Console.WriteLine("tick");
}
If you run that, it will output "tick" once per second until you press Enter.
That said, the problem of skipping ticks is easily handled by making a one-shot timer and re-enabling it after every tick. Like this:
private void DoIt()
{
// Timeout.Infinite makes it a one-shot timer
_myTimer = new Timer(MyTimerCallback, null, 1000, Timeout.Infinite);
// other code
}
private void MyTimerCallback(object state)
{
// do whatever processing is necessary
// and then restart the timer
_myTimer.Change(1000, Timeout.Infinite);
}
This way, the timer can't tick while a previous tick is still processing.
To ignore ticks when a previous tick handler is still running you can trivally handle this through an isRunning field:
private volatile int isRunning = 0;
public void Tick()
{
if (Interlocked.Exchange(ref isRunning, 1) == 0)
{
try
{
//do stuff
}
finally
{
isRunning = 0;
}
}
}
I have an Async DataGrid loading feature. Hence, i need to call WaitFor(). Here's that code:
WaitFor(TimeSpan.Zero, DispatcherPriority.SystemIdle);
And following are the 2 methods. Can someone explain what this methods are exactly doing?
public static void WaitFor(TimeSpan time, DispatcherPriority priority)
{
DispatcherTimer timer = new DispatcherTimer(priority);
timer.Tick += new EventHandler(OnDispatched);
timer.Interval = time;
DispatcherFrame dispatcherFrame = new DispatcherFrame(false);
timer.Tag = dispatcherFrame;
timer.Start();
Dispatcher.PushFrame(dispatcherFrame);
}
public static void OnDispatched(object sender, EventArgs args)
{
DispatcherTimer timer = (DispatcherTimer)sender;
timer.Tick -= new EventHandler(OnDispatched);
timer.Stop();
DispatcherFrame frame = (DispatcherFrame)timer.Tag;
frame.Continue = false;
}
You do not need any WaitFor(). Why waiting for something anyways? Just let the UI thread unfrozen and once data loaded the DataGrid will display them.
The methods you posted are doing the.... WaitFor mechanism. The method name explains it all :)
Here are few more details:
DispatcherTimer is a simple dumb Timer you might already know from basic C# just once tick method invoked it will be executed directly on UI thread, hence you do not need to care whether you are on UI thread or not. You always are :)
DispatcherTimer has a prority means if proprity set to high the tick invocation method will be called immediately after interval. If proprity is set to Background the tick method will be invoked when UI thread is not busy.
DispatcherFrame is the current scope you are in. Every displatcher operation has sort of scope. Each scope processes pending work items
Dispatcher.PushFrame is same as DoEvent() back when people used WinForms alot. To keep it simple with DoEvent you are forcing UI thread to do something.
To sum up you wait for things to get done in UI thread.
I hope this helps you any futher.
I'm really struggling with this. I'm creating a winforms application in visual studio and need a background timer that ticks once every half hour - the purpose of this is to pull down updates from a server.
I have tried a couple of different approaches but they have failed, either due to poor tutorial/examples, or to my own shortcomings in C#. I think it would be a waste of time to show you what I have tried so far as it seems what I tried was pretty far off the mark.
Does anyone know of a clear and simple way of implementing an asynchronous background timer that is easily understandable by a C# newbie?
// Create a 30 min timer
timer = new System.Timers.Timer(1800000);
// Hook up the Elapsed event for the timer.
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
...
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// do stuff
}
with the usual caveats of: timer won't be hugely accurate and might need to GC.KeepAlive(timer)
See also: Why does a System.Timers.Timer survive GC but not System.Threading.Timer?
Declare member variable in your form:
System.Timers.Timer theTimer;
On form load (or whatever other time you need to start update polling), do:
theTimer = new System.Timers.Timer(1800000);
theTimer.Elapsed += PollUpdates;
theTimer.Start();
Declare your PollUpdates member function like this:
private void PollUpdates(object sender, EventArgs e)
{
}
I think you need to know about all timer classes. See Jon's answer below.
What kind of timer are you using?
System.Windows.Forms.Timer will execute in the UI thread
System.Timers.Timer executes in a thread-pool thread unless you
specify a SynchronizingObject
System.Threading.Timer executes its callback in a thread-pool thread
In all cases, the timer itself will be asynchronous - it won't "take up" a thread until it fires.
Source: Do .NET Timers Run Asynchronously?
I want to repeat a function from the moment the program opens until it closes every few seconds.
What would be the best way to do this in C#?
Use a timer. There are 3 basic kinds, each suited for different purposes.
System.Windows.Forms.Timer
Use only in a Windows Form application. This timer is processed as part of the message loop, so the the timer can be frozen under high load.
System.Timers.Timer
When you need synchronicity, use this one. This means that the tick event will be run on the thread that started the timer, allowing you to perform GUI operations without much hassle.
System.Threading.Timer
This is the most high-powered timer, which fires ticks on a background thread. This lets you perform operations in the background without freezing the GUI or the main thread.
For most cases, I recommend System.Timers.Timer.
For this the System.Timers.Timer works best
// Create a timer
myTimer = new System.Timers.Timer();
// Tell the timer what to do when it elapses
myTimer.Elapsed += new ElapsedEventHandler(myEvent);
// Set it to go off every five seconds
myTimer.Interval = 5000;
// And start it
myTimer.Enabled = true;
// Implement a call with the right signature for events going off
private void myEvent(object source, ElapsedEventArgs e) { }
See Timer Class (.NET 4.6 and 4.5) for details
Use a timer. Keep in mind that .NET comes with a number of different timers. This article covers the differences.
There are lot of different Timers in the .NET BCL:
System.Timers.Timer
System.Threading.Timer
System.Windows.Forms.Timer
System.Web.UI.Timer
System.Windows.Threading.DispatcherTimer
When to use which?
System.Timers.Timer, which fires an event and executes the code in one or more event sinks at regular intervals. The class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.
System.Threading.Timer, which executes a single callback method on a thread pool thread at regular intervals. The callback method is defined when the timer is instantiated and cannot be changed. Like the System.Timers.Timer class, this class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.
System.Windows.Forms.Timer (.NET Framework only), a Windows Forms component that fires an event and executes the code in one or more event sinks at regular intervals. The component has no user interface and is designed for use in a single-threaded environment; it executes on the UI thread.
System.Web.UI.Timer (.NET Framework only), an ASP.NET component that performs asynchronous or synchronous web page postbacks at a regular interval.
System.Windows.Threading.DispatcherTimer, a timer that's integrated into the Dispatcher queue. This timer is processed with a specified priority at a specified time interval.
Source
Some of them needs explicit Start call to begin ticking (for example System.Timers, System.Windows.Forms). And an explicit Stop to finish ticking.
using TimersTimer = System.Timers.Timer;
static void Main(string[] args)
{
var timer = new TimersTimer(1000);
timer.Elapsed += (s, e) => Console.WriteLine("Beep");
Thread.Sleep(1000); //1 second delay
timer.Start();
Console.ReadLine();
timer.Stop();
}
While on the other hand there are some Timers (like: System.Threading) where you don't need explicit Start and Stop calls. (The provided delegate will run a background thread.) Your timer will tick until you or the runtime dispose it.
So, the following two versions will work in the same way:
using ThreadingTimer = System.Threading.Timer;
static void Main(string[] args)
{
var timer = new ThreadingTimer(_ => Console.WriteLine("Beep"), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
Console.ReadLine();
}
using ThreadingTimer = System.Threading.Timer;
static void Main(string[] args)
{
StartTimer();
Console.ReadLine();
}
static void StartTimer()
{
var timer = new ThreadingTimer(_ => Console.WriteLine("Beep"), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
}
But if your timer disposed then it will stop ticking obviously.
using ThreadingTimer = System.Threading.Timer;
static void Main(string[] args)
{
StartTimer();
GC.Collect(0);
Console.ReadLine();
}
static void StartTimer()
{
var timer = new ThreadingTimer(_ => Console.WriteLine("Beep"), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
}