Execute function every X minutes - c#

I'm a little bit confused about how this should work. I have multiple objects saved in a XML file and those objects have a property for TimeBetweenReposts (like 10 minutes) and TimesToRepost (like 20 times).
Each object in part should trigger a function every TimeBetweenReposts minutes.
How can I do this?

You have a few options, your most simple would be to create a separate thread which runs a function that looks something like this:
private void CheckTime()
{
while (!exitCondition) //So you can cleanly kill the thread before exiting the program.
{
if (nextCheck < DateTime.Now)
{
DoAction();
nextCheck = DateTime.Now + TimeBetweenReposts;
}
Thread.Sleep(1000); //Can be tweaked depending on how close to your time it has to be.
}
}
Otherwise you could make entries in the system task scheduler.

You can use a Timer to do something every X seconds, or minutes or whatever you need.
You can implement a Timer like this :
public class XMLFilesManager
{
Timer tm = null;
public XMLFilesManager()
{
this.tm.Elapsed += new ElapsedEventHandler(XMLFilesManagerTimer_Elapsed);
this.tm.AutoReset = true;
this.tm = new Timer(60000);
}
public void Start()
{
this.tm.Start();
}
public void Stop()
{
this.tm.Stop();
}
protected void XMLFilesManagerTimer_Elapsed(object sender, ElapsedEventArgs e)
{
this.tm.Stop();
try
{
Execute();
}
catch (Exception ex)
{
// LOG ERROR
}
finally
{
this.tm.Start();
}
}
private void Execute()
{
// PUT YOUR BUSINESS LOGIC HERE
}
}
Then, you can add a property to store the history of your execution, like :
// History of your object executions : object's identifier, last execution time and nb times you have execute the function for this object
List<Tuple<int,DateTime,int>> objectExecutionHistory = null;
And in the execute function, loop on your xml objects, and do what you have to do.

Related

C# object reference gets SOMETIMES lost in Threads that end via EventHandler

I have a strange problem with following code, that is started about every minute.
Normally everything works fine, but sometimes the HandleCalcStatistikMarkersDone function raises an error because of a NullReferenceException.
I try to explain with the code:
I have a class Strategies. This class is started about every minute to calculate and update some information in a MySQL database. This class is instantiated multiple times in separate threads within a ticker on a form.
public partial class mainForm: Form
{
//do something including ticker, that starts RunStatistik about every minute after the previous thread ended
private void RunStatistik()
{
foreach (InternalObject objPar in InternalObjects)
{
Strategies.StrategyParameter giveParms = new Strategies.StrategyParameter();
giveParms.pair= objPar.pair;
Strategies strat = new Strategies();
Thread calcStatistikThread = new Thread(new ParameterizedThreadStart(strat.CalcCoinStatistik));
calcStatistikThread.Start(giveParms);
}
}
}
Internally in the upper initiated Strategies thread, there are stared some additional threads.
Those threads have a "DoneEvent" which is raised at the end of the function.
To notice, that all threads have ended before the main thread ends, I collect all subthreads in a List CalcStatistikMarkersThreads and wait until the list is empty.
The subthreads should remove themselves out of the upper List via the ThreadDone event.
But sometimes the searched thread (CalcStatistikMarkersThreads.Find) is not found anymore and I get a NullReferenceException.
The question is why?!
Could you tell me, why? And possibly how to prevent?
Thanks in advance.
class Strategies
{ public event EventHandler ThreadDone;
private List<Thread> CalcStatistikMarkersThreads;
//do something
public void CalcCoinStatistik(object parameters)
{
StrategyParameter givenParms = (StrategyParameter)parameters;
Pair internalPair = givenParms.pair
//do something
if (CalcStatistikMarkersThreads == null)
{
CalcStatistikMarkersThreads = new List<Thread>();
}
foreach (InternalTodo in InternalToDos)
{
Strategies strat = new Strategies();
CalcStatistikMarkersParameter csp = new CalcStatistikMarkersParameter();
csp.parm1 = param;
strat.ThreadDone += HandleCalcStatistikMarkersDone;
Thread candleCalc = new Thread(new ParameterizedThreadStart(strat.CalcStatistikMarkers));
CalcStatistikMarkersThreads.Add(candleCalc);
candleCalc.Start(csp);
while (CalcStatistikMarkersThreads.Count != 0)
{
Task.Delay(1000).Wait();
}
}
}
public void CalcStatistikMarkers(object parm)
{
//do something
if (ThreadDone != null)
ThreadDone(this, new ThreadInfoEventArgs(Thread.CurrentThread.ManagedThreadId));
}
public void HandleCalcStatistikMarkersDone(object sender, EventArgs e)
{
Guid workGUID = Guid.NewGuid();
ThreadInfoEventArgs tEv = (ThreadInfoEventArgs)e;
Thread currentThread;
try
{
currentThread = CalcStatistikMarkersThreads.Find(xy => xy.ManagedThreadId == tEv.ThreadID);
//HERE THE NullReferenceException is raised sometimes
CalcStatistikMarkersThreads.Remove(currentThread);
}
catch (Exception ex)
{
throw ex;
}
}
public class ThreadInfoEventArgs : EventArgs
{
private int threadID;
public ThreadInfoEventArgs(int trID)
{
this.threadID = trID;
}
public int ThreadID
{
get { return threadID; }
}
}
}
Cheers
Air

How to get back to function from timed event

Okay so I have a function called readSensor which you guessed it.. reads a sensor.
But the sensors usually take about 100ms to respond. So in the readSensor function I am basically just starting a timer.
On the timed event I read the serialport and get my response.
However this means that my response is in the onTimedEvent when I want it to be in the readSensor function..
Basically from the main form I want to be able to do this.
value = readSensor()
when at the minute all I can do is readSensor() and then I can see the response is coming back by displaying it in a messagebox once the timedEvent fires.
here is my code. (I have missed out loads of serialport setup and stuff but hopefully you can see the problem I am in)
I don't want to just wait in the function for 100ms though polling the timer as that will make my program slow..
I want to somehow get the response back to the readSensor function and then back to the form.
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Timers;
namespace readSensor
{
public partial class readSens : UserControl
{
public readSens()
{
InitializeComponent();
}
private System.Timers.Timer rTimer;
SerialPort sp = new SerialPort();
private void setupTimer()
{
// Create a timer with a 100ms response.
rTimer = new System.Timers.Timer(100);
rTimer.SynchronizingObject = this;
// Hook up the Elapsed event for the timer.
rTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
string response = getResponse();
}
public string getResponse()
{
string status = "";
byte[] readBuffer = new byte[255];
if (sp.IsOpen)
{
if (sp.BytesToRead > 0) //there is data to read
{
int length = sp.BytesToRead;
for (int i = 0; i < length; i++)
{
readBuffer[i] = (byte)sp.ReadByte();
status = "pass";
return status;
}
}
}
public void readSensor(byte addr)
{
if (!sp.IsOpen)
{
openPort();
readSensor(addr); // calls itself again once port is opened
}
else if (sp.IsOpen)
{
rTimer.Start();
}
else
{
MessageBox.Show("Port not opened yet");
}
}
}
}
In the main form I am basically just saying
setupTimer();
readSensor();
on a button click.
I don't think you can do it without some callback mechanism. You could implement a while loop but that is not eficient as it would introduce spinning.
My advice is to implement a proper async pattern or something simple like:
ReadSensor(addr, DoSomethingWithResult);
public void DoSomethingWithResult(string result)
{
Console.WriteLine (result);
}
public partial class ReadSens : UserControl
{
private Action<string> _responseCallback;
public void ReadSensor(byte addr, Action<string> responseCallback)
{
_responseCallback = responseCallback;
// initiate timer
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
string response = getResponse();
_responseCallback(response);
}
}
Start a separate thread, then from that thread write into a queue the results back in your main thread.
class Game1
{
//We declare a queue, which is like an array that we can extract and enter data easily in a FIFO (first in, first out) style list.
Queue<string> q = new Queue<string>();
public void threadStart(object obj)
{
//We get the result of your function, while our main function is still looping and waiting.
string result = readInput()
//We tell C# that the parameter we passed in, is in fact the Game1 class passed from "t.Start"
Game1 game = (Game1)obj;
//This puts our "result" into the queue.
game.q.Enqueue(result);
}
public void start()
{
//Declares a new thread, which will run "threadStart" function.
System.Threading.Thread t = new System.Threading.Thread(threadStart);
//We start the other thread (that will run in parallel) and pass "this" as the parameter.
t.Start(this);
//We loop over and over, sleeping, whilst the other function runs at the same time. This is called "multi- threading"
while (q.Count == 0)
{
System.Threading.Thread.Sleep(10);
}
//This gets the last-entered (oldest) value from the queue q.
string result = q.Deque();
}
}
So this sets off a thread to get the result, and then in my version, polls the queue for a while until the results come back, but in yours could do a bunch of stuff, as long as you check the queue every now and again for new data.
Edit: Added commenting to hopefully alleviate some of your questions.
Could be this approach a valid solution for you? I think you only are using Timer to wait the serialPort to be open, but it can be self-controlled with raising event.
public class SensorReader
{
private Sensor sensor;
private string lastResponse;
public SensorReader(SerialPort serialPort)
{
this.serialPort = aSerialPort.
this.sensor = new Sensor(serialPort);
this.sensor.PortOpen += PortOpenEventHandler(OnPortOpen);
}
private void OnPortOpen()
{
this.ReadPort();
}
public string ReadPort(byte address)
{
if (!this.sensor.IsOpen)
{
this.sensor.OpenPort();
this.lastResponse = "The serial port doesn't respond... yet!";
}
else
{
// Read response at this point.
this.lastResponse = this.GetResponse();
}
return this.lastResponse;
}
}
public class Sensor
{
private SerialPort serialPort;
public Sensor(SerialPort aSerialPort)
{
this.serialPort = aSerialPort;
}
public bool IsOpen
{
get { return this.serialPort.IsOpen; }
}
public delegate void PortOpenEventHandler(object sender, EventArgs e);
public event PortOpenEventHandler PortOpen;
public void OpenPort()
{
// Open port here...
// ... and throw the PortOpen event.
if (this.PortOpen != null)
{
this.PortOpen(this, EventArgs.Empty);
}
}
}

Run a method and countinue to the WebApp's lifetime

There is an application that collects news from rss of news agencies maybe like Google Reader!.
I want to call a method to update my links in DB in a period of the time and it continues to the Application life time.
something like a clock !!!
without any pause
I know some info about Threading
but the problem is :
Where can I call my Update method?
I have some classes that some of them derive from others and I use to layer in my Project
I call the method in Global.asax:
protected void Application_Start(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(UpdateRss));
thread.Start();
Thread.Sleep(1000);
}
public void UpdateRss()
{
while (true)
{
using (LinkService linkSrv = new LinkService())
{
linkSrv.UpdateLinksFromRSS();
}
}
}
and the definition of UpdateLinksFromRSS in LinkService is:
public void UpdateLinksFromRSS()
{
List<RssInfo> q;
using (RssService RssSrv = new RssService())
{
q = RssSrv.GetRssInfoes();
}
foreach (var item in q)
{
AddLink(item);
}
}
Honestly the problem is i have a property in BaseService that is defined like this:
public static System.Web.Caching.Cache Cache
{
get { return HttpContext.Current.Cache; }
}
when I run the project!
I got an error from this line: return HttpContext.Current.Cache;

Weird C# Threading ThreadInterrupted exception

I am developing an application simulating a network comprising a number of nodes that exchange messages. I try to simulate the transmission channel with a Queue where every node can place a message. Then, another entity takes over the message and delivers it to the specified node. Then, i want to signal (with an event) the end of a transmission phase when the message queue is idle for a certain amount of time, say X, namely no new messages have been added to the queue for X mseconds.
I understand that my case follows the consumer/producer paradigm. So far, i have done the following:
public class Com<T>
{
private Thread dispatcher;
private Queue<T> queue;
private int waitTime;
private Object locker;
private Timer timer;
public event EventHandler EmptyQueueEvent;
public Com()
{
queue = new Queue<T>();
locker = new Object();
waitTime = X;
timer = new Timer(FireEmpty, null, Timeout.Infinite,Timeout.Infinite);
dispatcher = new Thread(Serve);
dispatcher.IsBackground = true;
dispatcher.Start();
}
private void Serve()
{
while (true)
{
try
{
if (queue.Count == 0)
{
timer.Change(waitTime, 0);
Thread.Sleep(Timeout.Infinite);
}
}
catch (ThreadInterruptedException)
{
}
while (queue.Count != 0)
{
lock (locker)
{
deliver(queue.Dequeue());
}
}
}
}
private void deliver(T item)
{
// Do stuff
}
public void Add(T item)
{
timer.Change(Timeout.Infinite, Timeout.Infinite);
lock (locker)
{
queue.Enqueue(item);
}
dispatcher.Interrupt();
}
private void FireEmpty(object o)
{
//Fire Event
}
}
However, running my simulations proves that my synchronization is not enough, since I am sometimes getting a "ThreadInterruptedException" while trying to dequeue my message (in method Serve()). Note that the exception does not occur each time i run the simulation, but rather rarely: approximately every 850-1000 executions (i am running the execution iteratively)..
Does anybody have an idea what it is wrong with my code? :)
Have you tried locking before you attempt to get the Queue count? Like:
private void Serve()
{
while (true)
{
try
{
int count = 0;
lock(locker)
count= queue.Count;
if (count == 0)
{
timer.Change(waitTime, 0);
Thread.Sleep(Timeout.Infinite);
}
}
catch (ThreadInterruptedException)
{
}
while (queue.Count != 0)
{
lock (locker)
{
deliver(queue.Dequeue());
}
}
}
}
It's possible that an add is getting called at the same time you're trying to count the number of items. Also, you might want to consider one of the collections from System.Collections.Concurrent if you're using .net 4.0.
** UPDATE **
I just took a closer look at your code and had an "Oh duh" moment. You should be getting a ThreadInterruptException because you're calling delegate.Interrupt(). Check the MSDN documentation on that. I think what you need to do is use something like a ManualResetEvent and instead of calling Interrupt() do a WaitOne() on that event.
** UPDATE2 **
Here's some sample code that includes my other locking suggestion as well (on Gist):
https://gist.github.com/1683547

How to handle processing real-time events that fire before processing of previous event is complete (C#)

Suppose we have a listener to a real-time event that executes some block of code upon the event being triggered.
for our discussion lets say we have a MyTime class, that has a member currentTime.
we have set it up so that whenever the computer clock changes, the currentTime is set to the value of current time.
We've implemented the property changed INotifyPropertyChanged interface for our currentTime object:
public event PropertyChangedEventHandler PropertyChanged;
public string currentTime
{
get { return _currentTime; }
set { _currentTime= value; this.NotifyPropertyChanged("currentTime"); }
}
public void NotifyPropertyChanged(object sender, PropertyChangedEventArgs e) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
Some other class, say ProcessTime is listening to this event:
TimeChanged += new PropertyChangedEventHandler(PropertyChanged};
and it has a function that will execute something:
public void TimeChanged(object sender, PropertyChangedEventArgs e)
{
// Process lots of calculations
}
Since our computer clock changes all the time, it will keep firing the event.
In my understanding, once the first time change occurs, we will execute the TimeChanged block. While we are executing, we will keep getting more and more notifications and processing them as fast as we can, creating a long queue of events still to be processed.
The problem is that after we process the first time change and move on to the next time change, the "real time" is already far ahead, and whatever we are calculating we are calculating for something that happened in the past.
What we would like to do is to ignore all new events until we finish our original processing, and only then start listening again for the event.
Setting up multiple threads is not an option as it doesn't address the issue, and we do not want to process every time change, only those when our resources have been freed up.
Obviously I've used the time change and the above code as a demonstrative example, but it demonstrates concisely and adequately (IMHO) what we are trying to accomplish here.
I would imagine to use some kind of buffer, but my knowledge here is very very limited.
Thanks
Thanks for all the answers so far. Will start on implementing it. Will try to document successes / failures.
Well, first the event in question is not being called asynchronously. So Unless you're setting the time on constantly changing threads, the call to set the time won't come back and you won't set it again until all of the events have handled it. If you want to prevent this problem, you need to move event handling to a different thread.
Ultimately the complexity of the situation and exactly how real-time you want to be can dictate the ultimate answer to this. But, assuming you want something that's fairly robust for a relatively few number of threads (let's say a dozen), here's roughly how I'd go about doing this.
private var _Callbacks = new List<PropertyChangedEventHandler>();
public event PropertyChangedEventHandler PropertyChanged
{
add
{
lock(_Callbacks)
_Callbacks.Add(value);
Thread Worker = new Thread(PollTime);
Worker.Background = true;
Worker.Start(value);
}
remove
{
lock(_Callbacks)
_Callbacks.Remove(value);
}
}
private void PollTime(object callback)
{
PropertyChangedEventHandler c = (PropertyChangedEventHandler)callback;
string LastReported = null;
while(true)
{
lock(_Callbacks)
if (!_Callbacks.Contains(c))
return;
if (LastReported != _currentTime)
{
LastReported = _currentTime;
c(this, new PropertyChangedEventArgs(name));
}
else
Thread.Sleep(10);
}
}
public string currentTime
{
get { return _currentTime; }
set { _currentTime= value; }
}
With that you get thread safety on your events (in case someone tries to subscribe/unsubscribe from them at an inopportune time), and each subscriber gets it's own thread to handle callbacks. The subscribers won't get all the same events, but they will all be notified when the time changes. Slower ones just won't get as many events because they'll lose some of the intermediate values. This won't notify if the time is reset with no change, but I don't see that as much of a loss. You may see problems if values alternate within a limited set, but with time that's not a problem.
For more reading on delegates, events and how they work, there's a very long, but very good piece at http://www.sellsbrothers.com/writing/delegates.htm
This would be my approach.
Do not let the consumer block the producer's event thread.
Create a lightweight "critical section" (basically an atomic condition variable) so that only one invocation of a consumer handler can be active at a given time.
Here is a complete example which implements this logic. There is an EventProducer and an EventConsumer. They can be configured to be faster or slower than each other as needed. The event producer creates a background thread to raise events. The EventConsumer uses a custom CriticalSectionSlim class with a simple TryEnter/Exit pattern to avoid simultaneous invocations of the handling code. It also posts the handling code to the thread pool using the default behavior of the .NET 4.0 Task class. If an exception occurs, it is rethrown from the main handler thread on the next invocation.
using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
internal sealed class Program
{
private static void Main(string[] args)
{
using (EventProducer producer = new EventProducer(TimeSpan.FromMilliseconds(250.0d)))
using (EventConsumer consumer = new EventConsumer(producer, TimeSpan.FromSeconds(1.0d)))
{
Console.WriteLine("Press ENTER to stop.");
Console.ReadLine();
}
Console.WriteLine("Done.");
}
private static class ConsoleLogger
{
public static void WriteLine(string message)
{
Console.WriteLine(
"[{0}]({1}) {2}",
DateTime.Now.ToString("hh:mm:ss.fff", CultureInfo.InvariantCulture),
Thread.CurrentThread.ManagedThreadId,
message);
}
}
private sealed class EventConsumer : IDisposable
{
private readonly CriticalSectionSlim criticalSection;
private readonly EventProducer producer;
private readonly TimeSpan processingTime;
private Task currentTask;
public EventConsumer(EventProducer producer, TimeSpan processingTime)
{
if (producer == null)
{
throw new ArgumentNullException("producer");
}
if (processingTime < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException("processingTime");
}
this.processingTime = processingTime;
this.criticalSection = new CriticalSectionSlim();
this.producer = producer;
this.producer.SomethingHappened += this.OnSomethingHappened;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing)
{
this.producer.SomethingHappened -= this.OnSomethingHappened;
}
}
private void OnSomethingHappened(object sender, EventArgs e)
{
if (this.criticalSection.TryEnter())
{
try
{
this.StartTask();
}
catch (Exception)
{
this.criticalSection.Exit();
throw;
}
}
}
private void StartTask()
{
if (this.currentTask != null)
{
this.currentTask.Wait();
}
this.currentTask = Task.Factory.StartNew(this.OnSomethingHappenedTask);
}
private void OnSomethingHappenedTask()
{
try
{
this.OnSomethingHappenedImpl();
}
finally
{
this.criticalSection.Exit();
}
}
private void OnSomethingHappenedImpl()
{
ConsoleLogger.WriteLine("BEGIN: Consumer processing.");
Thread.CurrentThread.Join(this.processingTime);
ConsoleLogger.WriteLine("END: Consumer processing.");
}
}
private sealed class EventProducer : IDisposable
{
private readonly TimeSpan timeBetweenEvents;
private readonly Thread thread;
private volatile bool shouldStop;
public EventProducer(TimeSpan timeBetweenEvents)
{
if (timeBetweenEvents < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException("timeBetweenEvents");
}
this.timeBetweenEvents = timeBetweenEvents;
this.thread = new Thread(this.Run);
this.thread.Start();
}
public event EventHandler SomethingHappened;
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing)
{
this.shouldStop = true;
this.thread.Join();
}
}
private void Run()
{
while (!shouldStop)
{
this.RaiseEvent();
Thread.CurrentThread.Join(this.timeBetweenEvents);
}
}
private void RaiseEvent()
{
EventHandler handler = this.SomethingHappened;
if (handler != null)
{
ConsoleLogger.WriteLine("Producer is raising event.");
handler(this, EventArgs.Empty);
}
}
}
private sealed class CriticalSectionSlim
{
private int active;
public CriticalSectionSlim()
{
}
public bool TryEnter()
{
return Interlocked.CompareExchange(ref this.active, 1, 0) == 0;
}
public void Exit()
{
Interlocked.Exchange(ref this.active, 0);
}
}
}
Well you can do something like this
as soon as you receive the event, unregister the event or in other words stop listening to event anymore.
Once you are done with your event processing start listening to event again by re-registering to event
public void TimeChanged(object sender, PropertyChangedEventArgs e)
{
//un register
TimeChanged -= new PropertyChangedEventHandler(PropertyChanged};
// Process lots of calculations
//re-register
TimeChanged += new PropertyChangedEventHandler(PropertyChanged};
}
I suggest that all scheduled tasks be placed in a queue ordered by process time (DateTime). The time event (tick) only needs to check the if the task at the head of the queue is 'pending'. That is if its time to process has been reached or passed. Then that task is removed from the queue, given the current time, and executed.
The task notifies the task queue when it has finished by a call back given in the execute method (that presumably also took current time). The task queue will not execute any other tasks while a task is executing. When a task notifies completion the task queue will immediately check if the task, if any, at the head of the queue is pending and so on.
Now a nice refinement that can be done here when u have time ordered task queue is that instead of periodic ticks you set a timer to fire (or one time changed listener) when it is time to execute the task at the head of the queue as you always know the time to next event. No need to multiple listeners and one controller for how many are executing, etc.
interface ITask
{
void Execute(ITaskCallBack callBack, DateTime currentTime);
}
interface ITaskCallBack
{
void OnCompleted(ITask task); // The task parameter is needed for concurrency
}
Whenever a task is added or deleted the time to next event is updated.
Important: If you add a new task that happens to wants to execute at the same time as an existing task you should add it after all tasks for the same time. This avoids child tasks hogging the scheduler.
The timed queue is your task scheduler/controller. You can make it single threaded or multi threaded as you like. Although I do not see much point in multi threading unless your using multiple processors.
interface ITaskScheduler
{
void Add(ITask task, DateTime executeTime);
void Remove(ITask);
}
Another nice spin off here is that the scheduler knows the time scheduled and the time actually started. Hence you have valuable diagnostic for delayed tasks or latencies due to loading. Important if you system needs to performance deterministic.
Hope this makes sense and is useful.
Best regards

Categories

Resources