Threads and Timing

G

Guest

I posted this on the Windows CE Application Development newsgroup and was
told to post it here:
Hey,
I'm trying to get a peice of code to run repeatedly every X seconds and the whole
thing shouldn't run for more than Y seconds.

I tried using System.Threading.Timer and the period does the repeating forme
but I have two problems:
1 - The period has nothing to do with whether the code has finished executing or
not. So if the code requires 2 seconds to run and I specified a 1 sec repeat period
it would run every second and not a second after the one before finished
exceuting. (I've done some research and it seems that in regular .NET this can be
solved by joining threads anything similar or workaround for .NETCF??)

2 - I have to have a seperate thread running to moniter the overall time, can I
avoid that?

Thanks for the help
Samer


I'm not sure I understand your suggestions....can you explain further a bit?
Thanks
Samer

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
Check out my blog at:
samersaghir.blogspot.com
 
D

Daniel Moth

Just re-read my reply and it seems pretty clear. Have you got the code you
are running now and I can show exactly which changes to make if that helps.
Otherwise tell me which bit you don't understand...

Cheers
Daniel
 
G

Guest

Daniel,

I seem to be able to everything except stop the timer. I use

timer.Change(Timeout.Infinite,Timeout.Infinite)

but it isn't the solution. After a few trials it seems to be useful if the
period was being used because then if the Change() is applied the
TimerCallback won't be called again; but it doens't stop the timer. Is there
something I can use to just stop the timer in it's tracks?

Thanks
 
D

Daniel Moth

That is not my experience. Change(-1,-1) will stop the timer. BTW, -1 is
Infinite.

Make sure you are not starting any of the timers with a period other than -1
and in fact create them with -1,-1 (search constructors and all Change
methods).

Obviously, if the timer expires right at the moment you try to stop it then
it is too late. What interval are you using?

Also obvious, if you have started the timer with a period of -1 and it has
called you back, you don't have to stop it after it expires.

Maybe not so obvious, you should stop a timer as the first line/statement of
the TimerCallback handler and restart it if you need at the last line just
before the method exits.

You may also dispose a timer if you are not going to use it anymore...

If you still think Change(-1 doesn't stop your timer, post a small
reproducible sample...

Cheers
Daniel
 
G

Guest

This is a small sample (C#):

private TimeSpan stopTaskDuration = new TimeSpan(0,0,2);
private System.Threading.Timer executer;

public void TriggerEvents()
{
TimerCallback executercb = new TimerCallback(KickOffEvents);
TimerCallback timercb = new TimerCallback(OnTrigger);
executer = new System.Threading.Timer
(executercb,null,0,Timeout.Infinite);
System.Threading.Timer timer = new System.Threading.Timer
(timercb,null,stopTaskDuration,new
TimeSpan(0,0,0,0,-1));
}

private void KickOffEvents(object sender)
{
Thread.Sleep(4000);
MessageBox.Show("KickOffEvents: " + DateTime.Now.ToLongTimeString());

}

public void OnTrigger(object sender)
{
executer.Change(Timeout.Infinite,Timeout.Infinite);
MessageBox.Show("OnTrigger: " + DateTime.Now.ToLongTimeString());
}

What this is doing is launching KickOffEvents which is a 4 sec delay and at
the same time launching OnTrigger which uses .Change() to try to stop the
timer running the executer. But what happens is that you get the message box
from OnTrigger and the message box from KickOffEvents.
Shouldn't I just be getting the OnTrigger message box?

Thanks
Samer
 
G

Guest

Thread.Sleep() is not the actual function it was just to illustrate, so there
isn't anyway to stop a timer? No killing allowed?
 
S

Sergey Bogdanov

You can not stop a timer if it's been already started therefore instead
of Thread.Sleep(4000) in KickOffEvents method set dueTime:

executer = new System.Threading.Timer(executercb,null, 4000,
Timeout.Infinite);

Best regards,
Sergey Bogdanov
http://www.sergeybogdanov.com
 
D

Daniel Moth

Not sure what you are expecting your sample to do. Please read my previous
reply again. I sense a communication breakdown but we'll get there :)

Maybe it is a terminology problem. There are 3 stages of a timer:
1. Creation (with -1,-1 so it is not started)
2. Timer running (it has started)
3. Timer expires (it has called you back)

While the timer is in state 2, you can stop it.

Assuming the above is clear, my advice to you was to create timers
with -1,-1 so you don't mix state 1 with state 2. My other advice is to
start the timer with period=-1 so you don't mix state 2 with state 3.

Here is a sample:

In a form with two buttons place the following code, run it and click
button1. If you click button2 within 4 seconds the timer will not expire.

// Timer created with -1,-1
private System.Threading.Timer tmr = new System.Threading.Timer(new
TimerCallback(clbk), null, -1, -1);

// if timer expires msgbox shown
private static void clbk(object o){
MessageBox.Show("expired");
}

//Button1 starts the timer
private void button1_Click(object sender, System.EventArgs e){
tmr.Change(4000, -1);
}

// button2 stops the timer
private void button2_Click(object sender, System.EventArgs e){
tmr.Change(-1, -1);
}

Cheers
Daniel
 
G

Guest

I'm writing an app that requires some scheduling capabilities so I wanted to
give it the ability to kill a task if the task runs for more than a specific
period of time.
 
D

Daniel Moth

Use a flag (bool). When you want to kill the task set the flag. Check it
periodically from your long running task and if it is true then return.

Cheers
Daniel
 
G

Guest

I just tried it and it expired.....

Daniel Moth said:
Not sure what you are expecting your sample to do. Please read my previous
reply again. I sense a communication breakdown but we'll get there :)

Maybe it is a terminology problem. There are 3 stages of a timer:
1. Creation (with -1,-1 so it is not started)
2. Timer running (it has started)
3. Timer expires (it has called you back)

While the timer is in state 2, you can stop it.

Assuming the above is clear, my advice to you was to create timers
with -1,-1 so you don't mix state 1 with state 2. My other advice is to
start the timer with period=-1 so you don't mix state 2 with state 3.

Here is a sample:

In a form with two buttons place the following code, run it and click
button1. If you click button2 within 4 seconds the timer will not expire.

// Timer created with -1,-1
private System.Threading.Timer tmr = new System.Threading.Timer(new
TimerCallback(clbk), null, -1, -1);

// if timer expires msgbox shown
private static void clbk(object o){
MessageBox.Show("expired");
}

//Button1 starts the timer
private void button1_Click(object sender, System.EventArgs e){
tmr.Change(4000, -1);
}

// button2 stops the timer
private void button2_Click(object sender, System.EventArgs e){
tmr.Change(-1, -1);
}

Cheers
Daniel
 
G

Guest

Thanks guys!!

That'll kind of solve the problem, but it still doesn't kill it directly;
there's still a bit of a wait and it seems I have to live with that.

Thanks again
Samer
 
S

Sergey Bogdanov

Well, you may consider to use OpenNETCF.Threading.ThreadEx to create a
separate thread for your task and terminate it using Abort method *but*,
to tell the truth, you should avoid it because it's bad practice to
terminate job like this and as I know TerminateThread doesn't work as
expected in WindowsCE.

What I can suggest you is to rewrite your scheduler task in this manner
that when you set flag "time to exit" it will gracefully complete all
operations and exit:

ThreadPool.QueueUserWorkItem(new WaitCallback(Task));
Thread.Sleep(1000);
_running = false;

void Task(object o)
{
_running = true;
while(_running)
{
DoTaskIteration();
}
}

Best regards,
Sergey Bogdanov
http://www.sergeybogdanov.com
 
D

Daniel Moth

You tried what exactly? Did the button2 click method run before the 4 second
interval? Works fine here...

Cheers
Daniel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top