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.
Related
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.
I need to do some operations on a certain interval (e.g. from 5 to 5 minutes in a loop) but need to be able to fully stop the thing whenever I want (on push of a button).
I was thinking into using a Timer class but events might fire even after the timer is stopped.
How can I have some code running on a timer and still be able to immediately bring everything to a complete stop?
Just so I am properly understood: By complete stop I mean that events stop and I can dispose of objects like the timer itself etc. I am not asking how to avoid having side effects from unexpected events that are fired after the timer is stopped!
Answer to this question depends a lot on a type of your operations.
Best scenario is to run a thread with a loop and listen to abort event.
static AutoResetEvent abort = new AutoResetEvent();
Thread worker = new Thread(WorkerThread);
void MainThread()
{
worker.Start();
Thread.Sleep(30000);
abort.Set();
}
void WorkerThread()
{
while(true)
{
if(abort.WaitOne(5000)) return;
// DO YOUR JOB
}
}
When you call abort.Set() from another thread, this one will exit.
But if your code is long running, you won't be able to exit until job is done.
To exit immediately you will have to abort thread, but this is not too wise because of resource consumption.
Alternatively, if your operation is long running (let's say you are going through long array), you can check "abort" event state from time to time (every iteration of loop, for example) like this abort.WaitOne(0).
The race condition with the timer is unavoidable since, as you say, the callbacks are executed from the thread pool. However, I believe you can safely dispose the timer even while it's still executing the events. An option which might help is if you consider using the System.Threading.Timer instead of System.Timers.Timer, for which you can call Timer.Dispose(WaitHandle) if you need to have a way to know when the timer events have finished executing. This will prevent race conditions for the cases where you also need to dispose of some other resource - a resource that the event consumer function will attempt to use.
As for the "immediate" requirement, the most immediate would probably be something that uses a synchronization primitive of sorts to stop execution. For example consider this:
static System.Timers.Timer timer;
static void Main(string[] args)
{
var cancelSource = new CancellationTokenSource();
timer = new System.Timers.Timer(200);
timer.Elapsed += new SomeTimerConsumer(cancelSource.Token).timer_Elapsed;
timer.Start();
// Let it run for a while
Thread.Sleep(5000);
// Stop "immediately"
cancelSource.Cancel(); // Tell running events to finish ASAP
lock (timer)
timer.Dispose();
}
class SomeTimerConsumer
{
private CancellationToken cancelTimer;
public SomeTimerConsumer(CancellationToken cancelTimer)
{
this.cancelTimer = cancelTimer;
}
public void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock (timer)
{
// Do some potentially long operation, that respects cancellation requests
if (cancelTimer.IsCancellationRequested)
return;
// More stuff here
}
}
}
This is a toy example, but it illustrates my point. The 3 lines that do the "stop immediately" have the following features:
By the time the Dispose call returns, none of the // More stuff here code will ever execute again.
None of the // More stuff here code can execute while the timer is being disposed, because of the lock.
The previous 2 features require the lock, but they prevent the timer from stopping "immediately" because on entering the lock it needs to wait for all timer events calls to finish if they have started. For this reason I added in the cancellation as the fastest way to abort the currently executing events while still guaranteeing that they won't be executing during timer dispose.
Note: if you need multiple timer events to execute simultaneously, consider using a ReaderWriterLockSlim instead of a monitor.
I'd consider one of these two options:
Put a safety check in the events that you need to execute. Something like a database flag. So even if the Timer fails to stop the event will bail out when the safety check fails.
Use something like Quartz.Net for scheduling. This is really heavy handed but it'll do what you want.
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.
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
I have an application that start System.Threading.Timer, then this timer every 5 seconds read some information from a linked database and update GUI on main form of application;
Since the System.Threading.Timer create another thread for the Tick event, i need to use Object.Invoke for updating User Interface on the main Form of application with code like this :
this.Invoke((MethodInvoker)delegate()
{
label1.Text = "Example";
});
The app work very well, but sometimes when the user close the main form and then close the application, if the second thread on timer_tick event is updating the user interface on main thread the user get an ObjectDisposedException.
How can i do for stop and close the threading timer before closing the main form and avoiding then Object disposed exception ?
This is a bit of a tricky proposition as you must ensure the following on a given Close event
The timer is stopped. This is fairly straight forward
The control being updated isn't disposed when the delegate is run. Again straight forward.
The code currently running off of a timer tick has completed. This is harder but doable
There are no pending Invoke methods. This is quite a bit harder to accomplish
I've run into this problem before and I've found that preventing this problem is very problematic and involves a lot of messy, hard to maintain code. It's much easier to instead catch the exceptions that can arise from this situation. Typically I do so by wrapping the Invoke method as follows
static void Invoke(ISynchronizedInvoke invoke, MethodInvoker del) {
try {
invoke.Invoke(del,null);
} catch ( ObjectDisposedException ) {
// Ignore. Control is disposed cannot update the UI.
}
}
There is nothing inherently wrong with ignoring this exception if you're comfortable with the consequences. That is if your comfortable with the UI not updating after it's already been disposed. I certainly am :)
The above doesn't take care of issue #2 though and it still needs to be done manually in your delegate. When working with WinForms I often use the following overload to remove that manual check as well.
static void InvokeControlUpdate(Control control, MethodInvoker del) {
MethodInvoker wrapper = () => {
if ( !control.IsDisposed ) {
del();
}
};
try {
control.Invoke(wrapper,null);
} catch ( ObjectDisposedException ) {
// Ignore. Control is disposed cannot update the UI.
}
}
Note
As Hans noted ObjectDisposedException is not the only exception that can be raised from the Invoke method. There are several others, including at least InvalidOperationException that you need to consider handling.
System.Timers.Timer is a horrible class. There is no good way to stop it reliably, there is always a race and you can't avoid it. The problem is that its Elapsed event gets raised from a threadpool thread. You cannot predict when that thread actually starts running. When you call the Stop() method, that thread may well have already been added to the thread pool but didn't get around to running yet. It is subject to both the Windows thread scheduler and the threadpool scheduler.
You can't even reliably solve it by arbitrarily delaying the closing of the window. The threadpool scheduler can delay the running of a thread by up to 125 seconds in the most extreme cases. You'll reduce the likelihood of an exception by delaying the close by a couple of seconds, it won't be zero. Delaying the close for 2 minutes isn't realistic.
Just don't use it. Either use System.Threading.Timer and make it a one-shot timer that you restart in the event handler. Or use a System.Windows.Forms.Timer, it is synchronous.
A WF Timer should be your choice here because you use Control.Invoke(). The delegate target won't start running until your UI thread goes idle. The exact same behavior you'll get from a WF timer.
Create two booleans called 'StopTimer' and 'TimerStopped'. Set the timer's AutoReset property to false. Then format the Elapsed method to the following:
TimerStopped = false;
Invoke((MethodInvoker)delegate {
// Work to do here.
});
if (!StopTimer)
timer.Start();
else
TimerStopped = true;
This way you are preventing a race condition, checking if the timer should continue and reporting when the method has reached its end.
Now format your FormClosing event as follows:
if (!TimerStopped)
{
StopTimer = true;
Thread waiter = new Thread(new ThreadStart(delegate {
while (!TimerStopped) { }
Invoke((MethodInvoker)delegate { Close(); });
}));
waiter.Start();
e.Cancel = true;
}
else
timer.Dispose();
If the timer hasn't stopped yet, a thread is launched to wait until it has done so and then try to close the form again.