Time based Method execution in C# - c#

I have a method send() that I wish to execute/call every 1 second. I'm having difficulty implementing this. So far this is what I have come up with in my main program:
bool done = false;
while (!done)
{
string vCurrent = RandomVoltage(220, 240) + "" + RandomCurrent(10, 13);
int seconds = RandomSec();
if (isEven(seconds))
send(vCurrent, "169.254.156.135");//send the string to the ip address
}
So basically I try call my send() method for every second of the current time that is even, and I skip the odd seconds, here is how I tried to implement that with my RandomSec() and isEven() methods:
private static readonly object syncLock = new object();
public static int RandomSec()
{
lock (syncLock)
{
return DateTime.Now.Second;
}
}
public static bool isEven(int sec)
{
if ((sec % 2) == 0)
return true;
else return false;
}
Now the problem is when I run the while loop in my program, my send() method sends a big bunch of strings in 1 second, then pauses for 1 second and then sends another big bunch of messages when the current second is even again. How can I get my program to execute my send() method only ONCE every 1 second, so that the send() method sends only 1 string every even second rather than say 20/30 of them. Is it possible for me to call my send() method in a time controlled loop? Any help is greatly appreciated.
Thanks in advance.

http://msdn.microsoft.com/en-us/library/system.timers.timer(v=VS.100).aspx

You can use the Timer class.
Sample Code from the above link:
public class Timer1
{
public static void Main()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 5 seconds.
aTimer.Interval=5000;
aTimer.Enabled=true;
Console.WriteLine("Press \'q\' to quit the sample.");
while(Console.Read()!='q');
}
// Specify what you want to happen when the Elapsed event is raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("Hello World!");
}
}

It is much easier to send a string, wait/sleep for a second (or two) and then send the next one.
Polling on the time, many times per second, will cause the effect you are experiencing

Related

Get Http Request with pause between every result from the lit

I want to build a simple API which just displays some data using the controller. The controller displays some dummy data using genfu and at the moment it is all retrieved at once, what i need to do is display each record after a certain amount of time, like, the first time i run the application i want 0 results, than, after one sec for example, the next one and so on, here's what i have so far in the controller, it's really really basic
// GET: api/<controller>
[HttpGet]
public IEnumerable<Contact> Get()
{
var data = _contactsGeneratorService.Collection(100);
return data;
}
I tried to use the thread.sleep option but it doesn't work in this case. Sorry, I am really really new to this.
Look into the C# Timer Control/Class. Here is an example from Microsoft's documentation:
using System;
using System.Timers;
public class Example
{
private static System.Timers.Timer aTimer;
public static void Main()
{
SetTimer();
Console.WriteLine("\nPress the Enter key to exit the application...\n");
Console.WriteLine("The application started at {0:HH:mm:ss.fff}", DateTime.Now);
Console.ReadLine();
aTimer.Stop();
aTimer.Dispose();
Console.WriteLine("Terminating the application...");
}
private static void SetTimer()
{
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
e.SignalTime);
}
}
For more examples, see this article: http://csharp.net-informations.com/gui/timer-cs.htm

Reset System.Timers.Timer to prevent Elapsed event

I am trying to use the Timer to trigger an event to send data across the network. I created a simple class to debug. Basically I have a List<string> I'd like to send. I want the following to happen:
Add string to List
Start Timer for 10 seconds
Add second string to List before Timer.Elapsed
Restart Timer back at 10 seconds.
So far I have this:
public static List<string> list;
public static Timer timer;
public static bool isWiredUp = false;
public static void Log(string value) {
if (list == null) list = new List<string>();
list.Add(value);
//this does not reset the timer, elapsed still happens 10s after #1
if (timer != null) {
timer = null;
}
timer = new Timer(10000);
timer.Start();
timer.Enabled = true;
timer.AutoReset = false;
if (!isWiredUp) {
timer.Elapsed += new ElapsedEventHandler(SendToServer);
isWiredUp = true;
}
}
static void SendToServer(object sender, ElapsedEventArgs e) {
timer.Enabled = false;
timer.Stop();
}
Any ideas?
You can use the Stop function followed immediately by the Start function to "restart" the timer. Using that you can create the Timer when the class is first created, wire up the Elapsed event at that time, and then do nothing but call those two methods when an item is added. It will either start, or restart, the timer. Note that calling Stop on a timer that hasn't yet been started just does nothing, it doesn't throw an exception or cause any other problems.
public class Foo
{
public static List<string> list;
public static Timer timer;
static Foo()
{
list = new List<string>();
timer = new Timer(10000);
timer.Enabled = true;
timer.AutoReset = false;
timer.Elapsed += SendToServer;
}
public static void Log(string value)
{
list.Add(value);
timer.Stop();
timer.Start();
}
static void SendToServer(object sender, ElapsedEventArgs e)
{
//TODO send data to server
//AutoReset is false, so neither of these are needed
//timer.Enabled = false;
//timer.Stop();
}
}
Note that rather than using a List it's very possible that you want to use a BlockingCollection<string> instead. This has several advantages. First, the Log methods will work if called at the same time from multiple threads; as is multiple concurrent logs could break the list. It also means that SendToServer can be taking items out of the queue at the same time that new items are added. If you use a List you'll need to lock all access to the list (which might not be a problem, but isn't as straightforward).
This kind of thing is very easy to achieve with IObservable (Rx).
Let us simplify matters by declaring a Subject<string> as your list to push onto using .OnNext. Once you have your subject, an observable, you can do what you want with a single 'line' of System.Reactive.Linq. This is illustrated in the following pseudo-c#
subject
.Buffer(<your timespan>,1) //buffer until either a value is added or the timeout expires
.Subscribe(x =>
{
if (x.Count == 0) //the timeout expired so send on
{
SendAccumulatedListToServer(<your list>);
<clear your list>
}
else
{
<your list>.Add(x);
}
});
What you are implementing is totally the wrong way to go about doing this. Have a look at the consumer producer model:
http://msdn.microsoft.com/en-us/library/hh228601.aspx
What you are trying to do is very commonly called the Consumer/Producer dataflow model. Essentially you have something generating a list of data that is to be sent somewhere, rather than sending it each time an item is added to the list you would like to send them in groups.. So you have a producer (the code putting data to be sent) and a consumer (the code sending the data).
Generally this problem is solved by spawning a thread that watches the list (usually a queue) and sends the data at regulary intervals, the best way to do this is using an EventWaitHandle.
Here is some very simplified code as an example
class ServerStuff
{
public void Init()
{
datatosend = new List<string>();
exitrequest = new EventWaitHandle(false, EventResetMode.ManualReset); //This wait handle will signal the consumer thread to exit
Thread t = new Thread(new ThreadStart(_RunThread));
t.Start(); // Start the consumer thread...
}
public void Stop()
{
exitrequest.Set();
}
List<string> datatosend;
EventWaitHandle exitrequest;
public void AddItem(string item)
{
lock (((ICollection)datatosend).SyncRoot)
datatosend.Add(item);
}
private void RunThread()
{
while (exitrequest.WaitOne(10 * 1000)) //wait 10 seconds between sending data, or wake up immediatly to exit request
{
string[] tosend;
lock (((ICollection)datatosend).SyncRoot)
{
tosend = datatosend.ToArray();
datatosend.Clear();
}
//Send the data to Sever here...
}
}
}

C#: Measure time taken and exit function when time elapsed

I would like to run a function (funcA) and use another function (timerFunc) as a timer. If the running function (funcA) has run for 10 seconds, I would like to exit it using the timer function (timerFunc). Is this possible? Basically what I am trying to do:
void funcA() {
// check event 1
// check event 2
// check event 3
// time reaches max here! --exit--
//check event 4
}
If not, what is the best way to handle such scenarios? I have considered using a stop-watch but I'm not sure if that is the best thing to do, mainly because I do not know after what event the timeout will be reached.
Thread t = new Thread(LongProcess);
t.Start();
if (t.Join(10 * 1000) == false)
{
t.Abort();
}
//You are here in at most 10 seconds
void LongProcess()
{
try
{
Console.WriteLine("Start");
Thread.Sleep(60 * 1000);
Console.WriteLine("End");
}
catch (ThreadAbortException)
{
Console.WriteLine("Aborted");
}
}
You could put all of the events into an array of Action or other type of delegate, then loop over the list and exit at the appropriate time.
Alternately, run all of the events in a background thread or Task or some other threading mechanism, and abort/exit the thread when you get to the appropriate time. A hard abort is a bad choice, as it can cause leaks, or deadlocks, but you could check CancellationToken or something else at appropriate times.
I would create a list and then very quickyl:
class Program
{
static private bool stop = false;
static void Main(string[] args)
{
Timer tim = new Timer(10000);
tim.Elapsed += new ElapsedEventHandler(tim_Elapsed);
tim.Start();
int eventIndex = 0;
foreach(Event ev in EventList)
{
//Check ev
// see if the bool was set to true
if (stop)
break;
}
}
static void tim_Elapsed(object sender, ElapsedEventArgs e)
{
stop = true;
}
}
This should work for a simple scenario. If it's more complex, we might need more details.

Quick while stopping

i have this code:
private STOP = false;
public void Start()
{
while(!STOP)
{
//do some work
Thread.Sleep(15000);
}
}
public void Stop()
{
STOP = true;
}
But using this code sometimes need to wait a 15 secs, how to quickly stop this cycle or maybe need to use other code?
Thanks!
Something along the lines of:
private System.Threading.ManualResetEvent STOP = new System.Threading.ManualResetEvent(false);
public void Start()
{
while(true)
{
//do some work
if(STOP.WaitOne(15000))
break;
}
}
public void Stop()
{
STOP.Set();
}
Whenever you find yourself writing a loop that does something, then waits a relatively long period of time (even one second is a long time!) to do it again, you should eliminate the loop and use a timer. For example, your code above can be re-written:
System.Threading.Timer MyTimer;
public void Start()
{
MyTimer = new Timer((s) =>
{
DoSomeWork();
}, null, 15000, 15000);
}
The timer will be triggered every 15 seconds to do the work. When it's time to shut down the program, just dispose of the timer.
public void Stop()
{
MyTimer.Dispose();
}
This will be more efficient than using a separate thread that spends most of its time sleeping, but still consuming system resources.
Use ManualResetEvent.WaitOne with timeout.
manualResetEvent.WaitOne(timeout)
Set the event to wake it up, or it will wake up when timed out.
See this related question.

Non-reentrant C# timer

I'm trying to invoke a method f() every t time, but if the previous invocation of f() has not finished yet, wait until it's finished.
I've read a bit about the available timers but couldn't find any good way of doing what I want, save for manually writing it all. Any help about how to achieve this will be appreciated, though I fear I might not be able to find a simple solution using timers.
To clarify, if t is one second, and f() runs the arbitrary durations I've written below, then:
Step Operation Time taken
1 wait 1s
2 f() 0.6s
3 wait 0.4s (because f already took 0.6 seconds)
4 f() 10s
5 wait 0s (we're late)
6 f() 0.3s
7 wait 0.7s (we can disregard the debt from step 4)
Notice that the nature of this timer is that f() will not need to be safe regarding re-entrance, and a thread pool of size 1 is enough here.
Use a System.Threading.Timer. Initialize it with a period of Timeout.Infinite so it acts like a one-shot timer. When f() completes, call its Change() method to recharge it again.
You could just use a 'global' level var (or more likely, a public property in the same class as f()) which returns true if f() is already running.
So if f() was in a class named TimedEvent, the first thing f() would do is set Running true
That way your timer fires every second, then launches the timed event if it isnt already running
if (!timedEvent.Running) timedEvent.f()
You commented that f() wouldnt repeat immediately if it took longer than the timer interval. Thats a fair point. I would probably include logic like that inside f() so that Running stays true. So it would look something like this:
public void f(int t) // t is interval in seconds
{
this.running = true;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
do
{
stopwatch.Reset();
// Do work here
} while (stopWatch.Elapsed.Seconds > t); // repeat if f() took longer than t
this.running = false;
}
You can use a non-restarting timer, then manually restart the timer after the method finishes.
Note that this will result in timing that is somewhat different from what you're asking for. (There will always be a gap of t time between invocations)
You could solve that by setting the interval to lastTick + t - Now, and running the method immediately if that's <= 0.
Beware of race conditions if you need to stop the timer.
You cannot get a timer to call you at exactly scheduled intervals. All timers do is call you back no sooner than the requested time.
Some timers are better than others (e.g. Windows.Forms.Timer is very erratic and unreliable compared to System.Threading.Timer)
To stop your timer being called re-entrantly, one approach is to Stop the timer while your method is running. (Depending on the type of timer you use, you either stop it and start it again when your handler exits, or with some timers you can request a single callback rather than repeating callbacks, so each execution of your handler simply enqueues the next call).
To keep the timing relatively even between these calls you can record the time since your handler last executed and use that to calculate the delay until the next event is required. e.g. If you want to be called once per second and your timer completed provcessing at 1.02s, then you can set up the next timer callback at a duration of 0.98s to accomodate the fact that you've already "used up" part of the next second during your processing.
A straightforward solution:
private class Worker : IDisposable
{
private readonly TimeSpan _interval;
private WorkerContext _workerContext;
private sealed class WorkerContext
{
private readonly ManualResetEvent _evExit;
private readonly Thread _thread;
private readonly TimeSpan _interval;
public WorkerContext(ParameterizedThreadStart threadProc, TimeSpan interval)
{
_evExit = new ManualResetEvent(false);
_thread = new Thread(threadProc);
_interval = interval;
}
public ManualResetEvent ExitEvent
{
get { return _evExit; }
}
public TimeSpan Interval
{
get { return _interval; }
}
public void Run()
{
_thread.Start(this);
}
public void Stop()
{
_evExit.Set();
}
public void StopAndWait()
{
_evExit.Set();
_thread.Join();
}
}
~Worker()
{
Stop();
}
public Worker(TimeSpan interval)
{
_interval = interval;
}
public TimeSpan Interval
{
get { return _interval; }
}
private void DoWork()
{
/* do your work here */
}
public void Start()
{
var context = new WorkerContext(WorkThreadProc, _interval);
if(Interlocked.CompareExchange<WorkerContext>(ref _workerContext, context, null) == null)
{
context.Run();
}
else
{
context.ExitEvent.Close();
throw new InvalidOperationException("Working alredy.");
}
}
public void Stop()
{
var context = Interlocked.Exchange<WorkerContext>(ref _workerContext, null);
if(context != null)
{
context.Stop();
}
}
private void WorkThreadProc(object p)
{
var context = (WorkerContext)p;
// you can use whatever time-measurement mechanism you want
var sw = new System.Diagnostics.Stopwatch();
int sleep = (int)context.Interval.TotalMilliseconds;
while(true)
{
if(context.ExitEvent.WaitOne(sleep)) break;
sw.Reset();
sw.Start();
DoWork();
sw.Stop();
var time = sw.Elapsed;
if(time < _interval)
sleep = (int)(_interval - time).TotalMilliseconds;
else
sleep = 0;
}
context.ExitEvent.Close();
}
public void Dispose()
{
Stop();
GC.SuppressFinalize(this);
}
}
How about using delegates to method f(), queuing them to a stack, and popping the stack as each delegate completes? You still need the timer, of course.
A simple thread is the easiest way to achieve this. Your still not going to be certain that your called 'precisely' when you want, but it should be close.... Also you can decide if you want to skip calls that should happen or attempt to catch back up... Here is simple helper routine for creating the thread.
public static Thread StartTimer(TimeSpan interval, Func<bool> operation)
{
Thread t = new Thread(new ThreadStart(
delegate()
{
DateTime when = DateTime.Now;
TimeSpan wait = interval;
while (true)
{
Thread.Sleep(wait);
if (!operation())
return;
DateTime dt = DateTime.Now;
when += interval;
while (when < dt)
when += interval;
wait = when - dt;
}
}
));
t.IsBackground = true;
t.Start();
return t;
}
For the benefit of people who land here searching for "re-entrancy": (I know this may be too late for the original question)
If one is not averse to using open source libraries that already provide for such functionality, I have successfully achieved this through an implementation using Quartz.NET
When you create a job and attach a trigger, you can specify what should be done if a previous trigger has not completed executing it's job

Categories

Resources