C# WP7 singleton timer - c#

I have a singleton timer in my WP7 application however I have no idea how to get it to update a textblock everytime the timer ticks... Is there a way to get the event handler of the timer ticking and then update the textbox with the correct time?
Here is what I tried to use but wouldn't work:
public _1()
{
InitializeComponent();
Singleton.TimerSingleton.Timer.Tick += new EventHandler(SingleTimer_Tick);
}
void SingleTimer_Tick(object sender)
{
textBlock1.Text = Singleton.TimerSingleton.TimeElapsed.TotalSeconds.ToString();
}
Here is my Timer.cs SingleTon:
http://tech-fyi.net/code/timer.cs.txt

void SingleTimer_Tick(object sender)
The method above should be something like
void SingleTimer_Tick(object sender, EventArgs e)
And when you ask a question please get your terminology right and give more details. It'll help you get the right answer faster. For example when you say "the application won't let me call ..." what you actually mean is the compiler gives you an error.

The method SingleTimer_Tick gets executed on a non GUI thread. Call
textBlock1.Invoke(() => textBlock1.Text = Singleton.TimerSingleton.TimeElapsed.TotalSeconds.ToString());

I'm not sure which type your timer is. Some are used to raise events on a thread pool thread, others on the GUI thread. If you could tell us the type of your timer (System.Timers.Timer, System.Threading.Timer etc.) then I can tell you what it's used for. However, if I remember correctly, Tick is used for the GUI timer whereas Elapsed is used for other timers - I might be wrong.
At the risk of patronizing you, I'm going to ask if you've started your timer or not :) Usually a call to Start() or setting Enabled to true will kick off a timer object. If you expect the timer to already be running you should be able to check a property such as Enabled to assert that it's running before you hook up the event.
Apart from that I'd do some printf style debugging to check that the event's actually being raised.

Related

System.Timers.Timer hangs the Windows Forms application in c#

The code below shows a timer that ticks every 100* 1000(milliseconds) to show a pop up message for registration.The below code is working but unfortunately my application gets hang after some time.
I have searched in google and stackoverflow for this answer.But i couldnt find a correct answer to make my application work without getting hanged.
private System.Timers.Timer register_Timer = new System.Timers.Timer();
register_Timer.Interval = (100 * 1000);
register_Timer.Elapsed += new ElapsedEventHandler(register_Timer_Tick);
register_Timer.SynchronizingObject = this;
register_Timer.AutoReset = true;
register_Timer.Enabled = true;
System.GC.KeepAlive(register_Timer);
private void register_Timer_Tick(object sender, EventArgs e)
{
//Pop up to show register message
}
register_Timer.SynchronizingObject = this;
This completely defeats the reason for using System.Timers.Timer. It prevents the Elapsed event handler from being raised on a threadpool thread, the property ensures it will run on the UI thread. Which is what you wanted.
But you still get all the disadvantages of that Timer class. Particularly its habit for swallowing exceptions without a diagnostic is very ugly. As well as continuing to raise the Elapsed event after the form is closed, ensuring this cannot happen is a very difficult problem to solve, there are two inherent race conditions. .NET 1.0 had some design mistakes related to threading, this was one of them.
Just don't do this, use a System.Windows.Forms.Timer instead. It will work exactly like your timer, minus all the disadvantages.
The application hangs because you're doing a popup (I assume a MessageBox or some other modal dialog box). Of course the application is going to hang. You're putting a modal dialog up in the UI thread.
The problem isn't with the timer, but with your application design.

One another way to let Timer skip tick if the previous thread is still busy

I have the same problem as described in this topic How to let Timer skip tick if the previous thread is still busy
I don't know if I should create new topic for my problem, or I can "up" somehow existent thread (please let me know if i'm wrong creating new topic)
I wrote such solution:
Mutex refreshMutex = new Mutex();
void OnRefreshTimedEvent(object source, ElapsedEventArgs args)
{
try
{
refreshMutex.WaitOne();
// do work
} finally
{
refreshMutex.ReleaseMutex();
}
}
I think it's better because it's thread-safe and doesn't lock entiry object. I would appreciate any comments cause I'm pretty novice in C# :)
Does anyone see any potential problems with what I've shared? I can't ask as an answer on the other discussion.
upd Well it seems solution above doesn't work (thanks to user24601 for noticing). But I don't like the answer from referenced question because the call to serviceTimer.Stop() is not thread-safe. It could be a problem in the extreme frequent timers theoretically (and probably practically), especially if system is used intensively (100% CPU load etc.). I'm thinking now about such pattern:
[MethodImpl(MethodImplOptions.Synchronized)]
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
serviceTimer.Stop();
// do some heavy processing...
}
finally
{
serviceTimer.Start();
}
}
This does not actually solve the problem. The Elapsed event is raised on a threadpool thread. When there are a lot of active TP threads in your app, the thread that calls your Elapsed event handler may take several seconds to start running. In fact, several of them may be scheduled while this delay takes place. Stopping the timer does not prevent these delayed threads from running. You can still have more than one thread calling your Elapsed event handler concurrently.
Set the timer's AutoReset property to False. Call the timer's Start() method in the finally block of your Elapsed event handler to get it going again. Or use a System.Threading.Timer with a period of 0. That's an all-around better timer, it doesn't swallow exceptions without a diagnostic either, like System.Timers.Timer does.
Perhaps I'm missing something, but why don't you just disable AutoReset on the timer (assuming you're using System.Timers.Timer- you didn't specify)? Put a try/finally around your Elapsed handler impl to ensure that Start() always gets called when it's done. This way, your timer won't start again until the Elapsed handler has completed.

Firing method on interval with System.Threading.Timer in winForm C#

What I want to do is to use the System.Threading.Timer to execute a method with a interval.
My example code looks like this atm.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
System.Threading.Timer t1 = new System.Threading.Timer(WriteSomething, null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(10));
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Clear();
}
public void WriteSomething(object o)
{
textBox1.Text = "Test";
}
}
}
Isn't this suppost to execute the WriteSomething method every 10'th second. What rly happens is that the WriteSomething is executed when I run my application and after 10 seconds the application closes. Think I have missunderstood how this works, can anyone tell me how to do this with the System.Threading.Timer.
thanks in advance, code examples are very welcome
The more likely scenario is that it crashes after 10 seconds. You cannot touch any controls in the callback, it runs on the wrong thread. You'd have to use Control.BeginInvoke(). Which makes it utterly pointless to use a System.Threading.Timer instead of a System.Windows.Forms.Timer.
Be practical. Make it 100 milliseconds so you don't grow a beard waiting for the crash. And don't use an asynchronous timer to update the UI, it is useless.
FYI, there is nothing about System.Windows.Forms timer that doesn't allow you to create in code (it's not just a "drag-and-drop" timer). Code:
Constructor code:
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Tick += OnTimerTick;
timer.Interval = 10000;
timer.Start();
Event Handler:
private void OnTimerTick(object sender, EventArgs e)
{
// Modify GUI here.
}
Just to reiterate what Hans said, in a WinForms application all GUI elements are not inherently thread-safe. Almost all methods / properties on Control classes can only be called on the thread the GUI was created on. The System.Threading.Timer invokes its callback on a thread pool thread, not the the thread you created the timer on (see reference below from MSDN). As Hans said, you probably want a System.Windows.Forms.Timer instead, that will invoke your callback on the correct thread.
You can always verify whether you can call methods on a Control (assuring you're on the correct thread) by using the code:
System.Diagnostics.Debug.Assert(!InvokeRequired);
inside your event handler. If the assert trips, you're on a thread that cannot modify this Control.
Quote from MSDN help on System.Threading.Timer on the callback method you passed in the constructor:
The method does not execute on the
thread that created the timer; it
executes on a ThreadPool thread
supplied by the system.
Common error: need to keep timer variable as class member as garbage collector may kill it.

Why System.Timer doesn't change class member variable?

I have a while loop and in this loop, there is a if condition.
But condition will be changed by a timer. But timer never change global variable.
I cant understand.
Where is the problem?
Example:
bool enterHere = false;
Timer timer = new Timer(); //Timer Started
private void timer_Tick(object Sender, ...)
{
enterHere = true;
}
private void function()
{
while(...)
{
if(enterHere)
{
//Never enter here
}
}
}
As another lesson in why you should always post your real code when asking questions on SO...
It appears the solution to your problem is quite a bit simpler than the other answers suggest. The timer's Tick event is never going to be raised, thus the value of the enterHere variable is never going to be changed, because you never actually start the timer. More specifically, this line is incorrect:
Timer timer = new Timer(); //Timer Started
The constructor does not start the timer; you need to call its Start method. This is confirmed by the documentation, which says:
When a new timer is created, it is disabled; that is, Enabled is set to false. To enable the timer, call the Start method or set Enabled to true.
Absolutely no reason to muck about with things like Application.DoEvents if you don't have to.
I assume you're using a System.Windows.Forms.Timer in which case the Tick event will run on the same thread as your function(). You can put
Application.DoEvents();
Inside your loop to get the timer to tick. Alternatively you could use an other timer (such as the System.Threading one), which executes on a different thread.
What else are you doing in the WHILE(...) loop and have you checked the processor usage when your code is running? If the loop is running very quickly there is no time for your app to process it's messages and react to the timer message.
As deltreme says, inserting Application.DoEvents(); in the loop should give it a chance to process the message.
Ideally the timer should be running in a different thread if you have a loop like that. The timer will never be able to raise the event.
Alteratively you could call DoEvents() to allow the timer to do it's work

contextswitchdeadlock

Whilst debugging my program in VS 2008 I have come across the following error:
The CLR has been unable to transition from COM context 0x34fc1a0 to COM context 0x34fc258 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this
It appears to be deadlocking even though the code only contains a simple C# timer: See Snippet Below:
private void RequestWork()
{
// The timer will be re-intialised if there are still no wating jobs in the database
StopTimer();
// assign all the threads some work
InitialiseTimer();
}
/// <summary>
/// Initialise a timer with a timer interval configured from app.config. Enable the timer and
/// register an appropriate event handler
/// </summary>
private void InitialiseTimer()
{
if (m_Timer == null)
{
// look up the default backoff time from the config
string backOffInt = ConfigurationSettings.AppSettings["BackOffInterval"];
int backoffInterval = 1000;
m_Timer = new System.Timers.Timer();
// set the timer interval to 5 seconds
m_Timer.Interval = backoffInterval;
m_Timer.Elapsed += new ElapsedEventHandler(m_Timer_Elapsed);
}
m_Timer.Enabled = true;
}
private void StopTimer()
{
if (m_Timer != null)
{
m_Timer.Enabled = false;
}
}
void m_Timer_Elapsed(object p_Sender, ElapsedEventArgs p_E)
{
RequestWork();
}
As far as I know the timer should run, elapse and then initialise again, I can see no local reason for a deadlock.
I am aware of how to turn this error msg off but feel that this is not a solution, instead it is masking the problem.
You can turn this off if you think you've definitely not got a deadlock situation:
Debug->Exceptions->Managed Debug Assistants menu in Visual Studio and uncheck the ContextSwitchDeadlock
This is an infinite loop. You need to let your application pump some messages at least once every 60 seconds to prevent this exception to happen.
Try calling System.Threading.Thread.CurrentThread.Join(10) once in a while. There are other calls you can do that let the messages pump.
It seems that you are adding a new event handler each time you call InitialiseTimer. That way m_Timer_Elapsed will be called as many times as it has been added.
You should add the event handler just one time.
If your application hangs or not reponse even after you uncheck the box against contextswitchdeadlock. Put the following line before call of method or for loop.
In C#
System.Windows.Forms.Application.DoEvents();
and VB.NET / VB / ASP.NET
DoEvents()
Couple thoughts/questions:
1) The code snippet looks like your interval is every 1 second (not 5 as mentioned in the comments).
2) The big question is what is RequestWork() doing?
Without knowing what RequestWork() is doing, we can't really comment on why you are seeing a ContextSwitchDeadlock.
Somethings to think about with respect to this method
a) how long does it take?
b) is it accessing GUI elements?
Some MSDN comments on Elapsed:
If you use the Timer with a user
interface element, such as a form or
control, assign the form or control
that contains the Timer to the
SynchronizingObject property, so that
the event is marshaled to the user
interface thread.
-and-
The Elapsed event is raised on a
ThreadPool thread. If processing of
the Elapsed event lasts longer than
Interval, the event might be raised
again on another ThreadPool thread.
Thus, the event handler should be
reentrant.
I'm thinking since you have a 1 second timer, you might want to look into what happens in RequestWork and see how long its taking.

Categories