Multiple DB Checks by multiple Timers - c#

I am building a Winforms Application that does multiple checks on a DB containing sensitive data.
the DB is updating in high frequency 24/7, so the application will check the DB 24/7.
The highest requirement I have is to build the application modular.
That implies that if I need to add additional checks to the application in the future, I can add this with high confidence that i am not messing up the existing checks.
In addition, every check need to be able to Enable/Disable by itself.
I thought to do that by building additional Check Box & Timer combo for each check in the application.
In that way, any additional check is independent (have its own timer and logic) and adding a new check will not change a single line of code in the existing checks.
Code (Test application):
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void check1CheckBox_CheckedChanged(object sender, EventArgs e)
{
check1Timer.Enabled = check1CheckBox.Checked;
}
private void check2CheckBox_CheckedChanged(object sender, EventArgs e)
{
check2Timer.Enabled = check2CheckBox.Checked;
}
private void check3CheckBox_CheckedChanged(object sender, EventArgs e)
{
check3Timer.Enabled = check3CheckBox.Checked;
}
private void check1Timer_Tick(object sender, EventArgs e)
{
check1(); //check DB data
}
private void check2Timer_Tick(object sender, EventArgs e)
{
check2(); //check DB data
}
private void check3Timer_Tick(object sender, EventArgs e)
{
check3(); //check DB data
}
}
I have 2 questions:
1. If in the method explained above, every check is independent and have no way to interrupt/mess with the other checks?
2. What is the "cost" of adding many timers (10+) running in the same time, either in stability/ responsiveness/ timing?
None of the timers will block the form for a long time, every time consuming DB call will be Async (by await calls).
In practice: most of the checks need to run in 2-5 seconds frequency, the maximum frequency will be every second.
Every check have is own frequency and veriables.
Thank you.

The only possible problem I can see, which could be a quite serious problem though, is the problem of overlapping invocations of the event handlers. From the three timers provided by the .NET platform (System.Windows.Forms.Timer, System.Timers.Timer and System.Threading.Timer), none of them prevents overlapping, meaning that the same query could be sent to the database again before the completion of the previous query. The result is that the database could end up being bombarded with more requests than it can handle. Considering that the databases have the tendency to become larger day by day, resulting to queries that become progressively slower, having multiple timers with constant intervals could be a time-bomb for the health of the app, the database, or the system as a whole.
Here are some questions related with the overlapping behavior of the timers, with answers offering solutions to the problem:
Synchronizing a timer to prevent overlap
How to let Timer skip tick if the previous thread is still busy
Timed events overlapping during execution
Here is my own implementation of a non-overlapping Timer, with the behavior I would prefer if I had a similar problem to solve.
/// <summary>
/// Provides a mechanism for executing a method on a thread pool thread,
/// at intervals that are automatically extended to prevent overlapping.
/// </summary>
public class NonOverlappingTimer
{
private readonly object _locker = new object();
private readonly Func<Task> _function;
private CancellationTokenSource _cts = new CancellationTokenSource();
private bool _enabled = false;
private int _interval = 100;
public NonOverlappingTimer(Action action)
{
if (action == null) throw new ArgumentNullException(nameof(action));
_function = () => Task.Run(action);
AsyncLoop();
}
public NonOverlappingTimer(Func<Task> function)
{
if (function == null) throw new ArgumentNullException(nameof(function));
_function = () => Task.Run(function);
AsyncLoop();
}
private async void AsyncLoop()
{
while (true)
{
CancellationToken ct;
bool enabled;
int interval;
lock (_locker)
{
ct = _cts.Token;
enabled = _enabled;
interval = _interval;
}
var delayTask = Task.Delay(enabled ? interval : Timeout.Infinite, ct);
if (enabled) await _function().ConfigureAwait(false);
try
{
await delayTask.ConfigureAwait(false);
}
catch (OperationCanceledException) { } // Suppress this exception
}
}
public bool Enabled
{
get
{
lock (_locker) return _enabled;
}
set
{
CancellationTokenSource cts;
lock (_locker)
{
if (value == _enabled) return;
_enabled = value;
cts = _cts;
_cts = new CancellationTokenSource();
}
cts.Cancel();
}
}
public int Interval
{
get
{
lock (_locker) return _interval;
}
set
{
if (value < 0) throw new ArgumentOutOfRangeException(nameof(value));
CancellationTokenSource cts;
lock (_locker)
{
if (value == _interval) return;
_interval = value;
cts = _cts;
_cts = new CancellationTokenSource();
}
cts.Cancel();
}
}
}
Usage example:
var timer = new NonOverlappingTimer(async () =>
{
Console.WriteLine("Tick");
await Task.Delay(3000); // Simulate a lengthy I/O-bound operation
});
timer.Interval = 2000;
timer.Enabled = true;
Output: a "Tick" will be printed every 3 seconds, although the interval is 2 seconds.

Related

c# multiple tasks running in background independently without blocking each other

I have a C# Windows Service that runs a few tasks inside.
One of the tasks is a infinite async looping and the others are triggered from a Timer and then execute the task.
private readonly QueueProcessor _queueProcessor;
protected override void OnStart(string[] args)
{
// first task
_queueTask = _queueProcessor.Run(_cancellation.Token);
// second task
affiliate_timer = new System.Timers.Timer();
affiliate_timer.AutoReset = true;
affiliate_timer.Interval = _model.Interval_Affiliate * 60000;
affiliate_timer.Elapsed += new
System.Timers.ElapsedEventHandler(affiliate_timer_Elapsed);
// third task
invoice_timer = new System.Timers.Timer();
invoice_timer.AutoReset = true;
invoice_timer.Interval = _model.Interval_Invoice * 60000;
invoice_timer.Elapsed += new
System.Timers.ElapsedEventHandler(invoice_timer_Elapsed);
}
private void invoice_timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
if (!_isAffiliateBusy)
{
_isAffiliateBusy= true;
var task = Task.Run(() => StartAffiliateTask());
task.Wait();
_isAffiliateBusy= false;
}
}
private void invoice_timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
if (!_isInvoiceBusy)
{
_isInvoiceBusy = true;
var task = Task.Run(() => StartInvoiceTask());
task.Wait();
_isInvoiceBusy = false;
}
}
private void StartAffiliateTask()
{
_affiliateModule = new Modules.Affiliate();
_affiliateModule.RunSync();
}
private void StartInvoiceTask()
{
_invoiceModule = new Modules.Invoice();
_invoiceModule.RunSync();
}
This is my QueueProcessor class that implements await/async to execute a infinite looping job:
public class QueueProcessor
{
private readonly IQueueBroker _serviceBroker;
public QueueProcessor()
{
}
public async Task Run(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var receiveMessageResponse = await _serviceBroker.ReceiveMessageAsync("test", cancellationToken);
if (!receiveMessageResponse.Messages.Any())
{
continue;
}
foreach (var message in receiveMessageResponse.Messages)
{
// some other tasks here...
await _serviceBroker.DeleteMessageAsync(message, cancellationToken);
}
}
}
}
My Affiliate and Invoice module classes doesn't implement any await/async code inside looks like this:
public class Affiliate
{
/// <summary>
/// Start the sync process
/// </summary>
public void RunSync()
{
try
{
// some code here...
}
catch (Exception ex)
{
}
}
}
My question is:
When my queue procesor infinite loop is running, does my other tasks that are triggered by the timers still can run independently?
When I use:
var task = Task.Run(() => StartAffiliateTask());
task.Wait();
Does the Wait method stop the whole service thread until this task is finished? or that won't block my StartInvoiceTask to run independantly?
Any recommendation on the best way to have my 3 tasks running independant on each other?
Summing up multiple potential issues:
Race condition (access/write to _isBusy).
Potential deadlock (in low ThreadPool size).
Potential incosistent state of flag in case of errors or thread aborts (_isBusy can be left in 'true' state).
Further I will assume your 'task' should be running in single instance, so we will disgard timer callbacks if it is still running.
You should change your timer event handlers like so (best to just wrap it in some kind of class):
//the flag, do mention volatile modifier - it tells particular
//systems to watch for variable changes by reference,
//instead of just copying it into thread stack by value.
private volatile bool _isAffiliateBusy = false;
//sync object for flag to eliminate race condition
private object _affiliateSync = new object();
private void affiliate_timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
//very fast lookup at flag to filter threads which comes when task is still processing
if(_isAffiliateBusy)
return;
lock(_affiliateSync) //taking lock
{
//checking again for those threads which 'happen' to be faster than you think.
if(_isAffiliateBusy)
return;
//aquire lock for business 'task'
_isAffiliateBusy = true;
}
try
{
StartAffiliateTask();
}
finally
{
//resetting singleton business 'task' lock.
//do not forget to use finally block, to handle disposing
//even if something rise up in 'try' section - you will not be left with invalid state of flag.
_isAffiliateBusy = false;
}
}

WPF Task Manager: Handling Refreshing CPU Load Value?

I am currently somewhat new to c#/wpf (and coding in general). I decided to start another project, being a custom made "task manager" of sorts.
(While I use binding, this is NOT a MVVM project, so all answers welcome)
If you have ever opened task manager, you know that one of the main helpful tools it provides is a updating view of CPU/RAM/Whatever usage. Telling the user what percent of the resource they are using.
My problem is not getting the CPU percentage. I am unsure on how to refresh the text property for CPU load in the UI efficiently.
My first thought was that I should create a Background worker (which is probably correct) to separate the thread loads. However, I can't seem to wrap my mind on the solution to implement the background workers in a useful way.
The code is currently set up in this fashion:
When page is loaded, public BgWrk creates a new instance of it self.
Adds task to be called when ran.
BgWrk is ran.
New instance of method to be called is made.
Dispatcher is invoked on main thread to update UI.
Invoke consists of setting public string PerCpu (bound in other class, using INotifyPropertyChanged & all) on the return value of "grabber"'s CpuPerUsed.
BgWrk disposed.
Program loops (this is most likely the problem).
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
BgWrk = new BackgroundWorker();
BgWrk.DoWork += new DoWorkEventHandler(BackgroundWorker1_DoWork);
BgWrk.RunWorkerAsync();
}
private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
CpuInfoGrabber grabber = new CpuInfoGrabber();
Application.Current.Dispatcher.Invoke(new Action (() => Bnd.PerCpu = grabber.CpuPerUsed()));
BgWrk.Dispose();
}
}
Again the code works, but it is WAY to slow due to the load of retrieving all of that data. Any suggestions on how to make this work well are appreciated!
Thanks
Instead of looping you could use a timer to periodically poll for the CPU usage.
class Test
{
private System.Timers.Timer _timer;
public Test( )
{
_timer = new System.Timers.Timer
{
// Interval set to 1 millisecond.
Interval = 1,
AutoReset = true,
};
_timer.Elapsed += _timer_Elapsed;
_timer.Enabled = true;
_timer.Start( );
}
private void _timer_Elapsed( object sender, System.Timers.ElapsedEventArgs e )
{
// This handler is not executed on the gui thread so
// you'll have to marshal the call to the gui thread
// and then update your property.
var grabber = new CpuInfoGrabber();
var data = grabber.CpuPerUsed();
Application.Current.Dispatcher.Invoke( ( ) => Bnd.PerCpu = data );
}
}
I'd use Task.Run instead of a BackgroundWorker in your case:
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
//Keep it running for 5 minutes
CancellationTokenSource cts = new CancellationTokenSource(new TimeSpan(hours: 0, minutes: 5, seconds: 0));
//Keep it running until user closes the app
//CancellationTokenSource cts = new CancellationTokenSource();
//Go to a different thread
Task.Run(() =>
{
//Some dummy variable
long millisecondsSlept = 0;
//Make sure cancellation not requested
while (!cts.Token.IsCancellationRequested)
{
//Some heavy operation here
Thread.Sleep(500);
millisecondsSlept += 500;
//Update UI with the results of the heavy operation
Application.Current.Dispatcher.Invoke(() => txtCpu.Text = millisecondsSlept.ToString());
}
}, cts.Token);
}

Implementing queued tasks that start based on conditions

I am looking for the ideal/thread safe implementation of a task queue that will start each task based on an internal condition (which i also only want to be checked at a timed interval), but also check that there aren't too many other tasks running. I also want a way to return progress of each task in the queue.
To give some background, I have a FileSystemWatcher that sends an event on a new folder being made. I then want to put this into a queue to process the folder, when it is no longer locked. But at the same time I want to guard against too many instances of the Process task from running.
Heres some pseudo-code of what I am after.
private static void EventToQueue(object sender, EventArgs e)
{
ProcessQueue.Enqueue(Task, condition);
}
private static async void NewQueueObject(object sender, QueueObject e)
{
if (e.Condition && ProcessQueue.ActiveTask < 4)
{
var progress = new Progress<int>();
progress.ProgressChanged += ( s, e ) =>
{
UpdateProgress(e.Value);
};
await LongProcess(e, progress);
}
else
{
e.Delay(30);
}
}

Constant running process on a sperate thread blocking a UI thread

i am trying to use a third party telnet library "active expert" for a basic telnet session.
in my UI code behind i have something like
private async void Button_Click(object sender, RoutedEventArgs e)
{
var ts = new TelnetService();
await ts.DoConnect(node);
}
and my TelnetService looks like this
public class TelnetService
{
private Tcp objSocket = new Tcp();
private NwConstants objConstants = new NwConstants();
public string Responses { get; set; }
private Timer timer1 = new Timer();
public TelnetService()
{
timer1.Elapsed += timer1_Elapsed;
timer1.Interval = 100;
timer1.Start();
}
void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (objSocket.ConnectionState == objConstants.nwSOCKET_CONNSTATE_CONNECTED)
{
if (objSocket.HasData())
{
Responses += objSocket.ReceiveString() + "\r\n";
}
}
}
public Task DoConnect(Node node)
{
return Task.Factory.StartNew(() =>
{
objSocket.Protocol = objConstants.nwSOCKET_PROTOCOL_TELNET;
objSocket.Connect(node.IP, 23);
while (true)
{
if ((Responses == null) || (!Responses.Contains(node.WaitString))) continue;
//do something
Responses = "";
break;
}
});
}
}
there are two important pieces of functionalities.
First in the timer1_Elapsed function which is process that will keeps on ruining and checks if there is data on socket, and if there is, it will append it to a string "Response". and i am using "timer" for it.
Second in the DoConnect function which will check the"Response" string for a certain input. for this i am using async await and Task.
in a nutshell first one accumulating the Response and Second one checking the Response.
Problem is that it looks like the timer code in general and
objSocket.ReceiveString()
line specifically is causing the UI thread to halt for several seconds. which means after clicking the button i cannot move my main form on the screen however the code is running in a separate thread.
i have tried using pure Thread for this but it didn't helped either.
update
instead of timer i am using a method AccumulateResponse
public static void AccumulateResponse()
{
while (true)
{
if (objSocket.ConnectionState == objConstants.nwSOCKET_CONNSTATE_CONNECTED)
{
if (objSocket.HasData())
{
Responses += objSocket.ReceiveString() + "\r\n";
}
}
}
}
and calling it like
var t = new Task(TelnetService.AccumulateResponse);
t.Start();
await TelnetService.DoConnect(node);
still no luck
The DoConnect isn't your problem. It is your Timer Elapsed Event handler.
The timer elapsed event is NOT asynchronous. Only the DoConnect is.
If there is no asynchronous version of ReceiveString() from your third party lib, then use Task.Run there as well inside of an async timer1_elapsed method.

Producer-Consumer with a variation - How to synchronize with thread signal/wait?

While working on a large project I realized I was making a lot of calls to be scheduled in the future. Since these were fairly light-weight, I thought it might be better to use a separate scheduler.
ThreadPool.QueueUserWorkItem (() =>
{
Thread.Sleep (5000);
Foo (); // Call is to be executed after sometime
});
So I created a separate scheduler class that runs on its own thread and executes these events. I have 2 functions that access a shared queue from separate threads. I'd use a lock, but since one of the threads needs to sleep-wait, I wasn't sure how to release the lock.
class Scheduler
{
SortedDictionary <DateTime, Action> _queue;
EventWaitHandle _sync;
// Runs on its own thread
void Run ()
{
while (true)
{
// Calculate time till first event
// If queue empty, use pre-defined value
TimeSpan timeDiff = _queue.First().Key - DateTime.Now;
// Execute action if in the next 100ms
if (timeDiff < 100ms)
...
// Wait on event handle for time
else
_sync.WaitOne (timeDiff);
}
}
// Can be called by any thread
void ScheduleEvent (Action action, DataTime time)
{
_queue.Add (time, action);
// Signal thread to wake up and check again
_sync.Set ();
}
}
The trouble is, I'm not sure how to synchronize access to the queue between the 2 functions. I can't use a monitor or mutex, because Run() will sleep-wait, thus causing a deadlock. What is the right synchronization mechanism to use here? (If there a mechanism to atomically start the sleep-wait process and immediately release the lock, that might solve my problem)
How can I verify there is no race-condition?
Is this a variation of the producer consumer problem, or is there a more relevant synchronization problem-description?
While this is somewhat geared towards C#, I'd be happy to hear a general solution to this. Thanks!
OK, take 2 with Monitor/Pulse.
void Run ()
{
while (true)
{
Action doit = null;
lock(_queueLock)
{
while (_queue.IsEmpty())
Monitor.Wait(_queueLock);
TimeSpan timeDiff = _queue.First().Key - DateTime.Now;
if (timeDiff < 100ms)
doit = _queue.Dequeue();
}
if (doit != null)
; //execute doit
else
_sync.WaitOne (timeDiff);
}
}
void ScheduleEvent (Action action, DataTime time)
{
lock (_queueLock)
{
_queue.Add(time, action);
// Signal thread to wake up and check again
_sync.Set ();
if (_queue.Count == 1)
Monitor.Pulse(_queuLock);
}
}
The problem is easily solved, make sure the WaitOne is outside the lock.
//untested
while (true)
{
Action doit = null;
// Calculate time till first event
// If queue empty, use pre-defined value
lock(_queueLock)
{
TimeSpan timeDiff = _queue.First().Key - DateTime.Now;
if (timeDiff < 100ms)
doit = _queue.Dequeue();
}
if (doit != null)
// execute it
else
_sync.WaitOne (timeDiff);
}
_queueLock is a private helper object.
Since your goal is to schedule a task after a particular period of time, why not just use the System.Threading.Timer? It doesn't require dedicating a thread for the scheduling and takes advantage of the OS to wake up a worker thread. I've used this (removed some comments and other timer service functionality):
public sealed class TimerService : ITimerService
{
public void WhenElapsed(TimeSpan duration, Action callback)
{
if (callback == null) throw new ArgumentNullException("callback");
//Set up state to allow cleanup after timer completes
var timerState = new TimerState(callback);
var timer = new Timer(OnTimerElapsed, timerState, Timeout.Infinite, Timeout.Infinite);
timerState.Timer = timer;
//Start the timer
timer.Change((int) duration.TotalMilliseconds, Timeout.Infinite);
}
private void OnTimerElapsed(Object state)
{
var timerState = (TimerState)state;
timerState.Timer.Dispose();
timerState.Callback();
}
private class TimerState
{
public Timer Timer { get; set; }
public Action Callback { get; private set; }
public TimerState(Action callback)
{
Callback = callback;
}
}
}
The monitores were created for this kind of situation, simple problems that can cost mutch for the application, i present my solution to this very simple and if u want to make a shutdown easy to implement:
void Run()
{
while(true)
lock(this)
{
int timeToSleep = getTimeToSleep() //check your list and return a value
if(timeToSleep <= 100)
action...
else
{
int currTime = Datetime.Now;
int currCount = yourList.Count;
try{
do{
Monitor.Wait(this,timeToSleep);
if(Datetime.now >= (tomeToSleep + currtime))
break; //time passed
else if(yourList.Count != currCount)
break; //new element added go check it
currTime = Datetime.Now;
}while(true);
}
}catch(ThreadInterruptedException e)
{
//do cleanup code or check for shutdown notification
}
}
}
}
void ScheduleEvent (Action action, DataTime time)
{
lock(this)
{
yourlist.add ...
Monitor.Pulse(this);
}
}

Categories