Increment a Temporary / Timed Variable in C# - c#

Forgive the ignorance of this question, as I'm completely new to C#, but how would one go about setting and handling a temporary or timed variable? For example, whenever an event fires, I want to increment a counter. If the counter exceeds 3 within 60 seconds, I want to trigger another event. Elsewise, if 60 seconds passes and the counter isn't incremented, it resets back to 0.
Should I be using MemoryCache? Or is there some nifty flag I can set for variables to make them unset after a specified duration (assuming they aren't refreshed)? What would be the best way to go about accomplishing this simple task? Note that I'm not necessarily looking for someone to write it for me; just a helpful hand or suggestion to point me in the right direction. This is a rough outline of what I'm trying to accomplish:
private static int totalCount = 0;
private static double maxCount = 3;
private static double timeLimit = 60;
private static void TestEvent(object src, EventArgs mea)
{
totalCount++;
if (totalCount > maxCount)
{
DoSomething();
}
}
Thanks for any assistance you can offer. I make it a point to always reward helpful answers.

You could maintain a Queue<T> (see http://msdn.microsoft.com/en-us/library/7977ey2c.aspx), where each entry is the time that an event fired. When an event fires, you first remove from the queue any entries that are more than 60 seconds old (which is easy, because the queue is ordered by time, and the head of the queue is the oldest entry), then add a new entry for the event that just fired. If the count of the queue exceeds your threshold, then you have satisfied the condition you're looking for.
I recommend using DateTime.UtcNow instead of DateTime.Now for the time you store in the Queue<T>. UtcNow is much faster, and it avoids the problem that transitions from daylight savings time to standard time and vice versa can cause.
Here is some code off the top of my head (may need a little fixing up):
private static Queue<DateTime> eventQueue = new Queue<DateTime>();
private static int timeWindowSeconds = 60;
private static int threshold = 3;
private static void TestEvent(object src, EventArgs mea) {
DateTime now = DateTime.UtcNow;
DateTime tooOld = now.AddSeconds(-timeWindowSeconds);
// remove old entries
while((eventQueue.Count > 0) && (eventQueue.Peek() < tooOld)) {
eventQueue.Dequeue();
}
// add new entry
eventQueue.Enqueue(now);
// test for condition
if (eventQueue.Count >= threshold) {
eventQueue.Clear();
DoSomething();
}
}

You might do it like this:
private static int totalCount = 0;
private static double maxCount = 3;
private static TimeSpan timeLimit = TimeSpan.FromSeconds(60);
private static DateTime lastIncrementTime;
private static void TestEvent(object src, EventArgs mea)
{
// If the time between now and lastIncrementTime is more than the timeLimit...
if(DateTime.Now - lastIncrementTime > timeLimit)
{
totalCount = 0;
}
lastIncrementTime = DateTime.Now;
totalCount++;
if (totalCount > maxCount)
{
DoSomething();
}
}

You can use the StopWatch class.
On the form load event (if you want to count the 60 second from that event), start the timer,
Everytime in the click event,check how many seconds it is invoked your other method or so.

I'd do something like this:
private class SomeEventMonitor
{
public int Threshold { get ; private set ; }
public TimeSpan ThresholdWindow { get ; private set ; }
private DateTime marker ;
private int count ;
/// <summary>
/// public constructor
/// </summary>
/// <param name="threshold"></param>
/// <param name="window"></param>
public SomeEventMonitor( int threshold , TimeSpan window )
{
if ( threshold < 1 ) throw new ArgumentOutOfRangeException("threshold") ;
if ( window <= TimeSpan.Zero ) throw new ArgumentOutofRangeException("window") ;
this.Threshold = threshold ;
this.ThresholdWindow = window ;
Reset() ;
return ;
}
private void Reset()
{
this.marker = DateTime.Now ;
this.count = 0 ;
return ;
}
public event EventHandler ThresholdExceeded ;
private static readonly object latch = new object() ;
public void EventWatcher( object source , EventArgs eventArgs )
{
lock ( latch )
{
DateTime current = DateTime.Now ;
if ( ++count > Threshold )
{
TimeSpan window = current -marker ;
if ( window > ThresholdWindow )
{
ThresholdExceeded( this , new EventArgs() ) ;
Reset() ;
}
}
}
return ;
}
}

You can use another variable to log the time of changing the value of totalcount. check it with the current time and do whatever you want.
Here is the code...
private static int totalCount = 0;
private static double maxCount = 3;
private static double timeLimit = 60;
private static DateTime timeflag= DateTime.Now;
private static void TestEvent(object src, EventArgs mea)
{
if (timeflag.AddSeconds(timeLimit) < DateTime.Now)
{
totalCount = 0;
}
totalCount++;
timeflag = DateTime.Now;
if (totalCount > maxCount)
{
DoSomething();
}
}

There are myriad ways you could approach this. The first thing that comes to mind for me would be to use a Stopwatch object or a Timer object that starts on a background thread, and then write an event handler that can subscribe to the event in which you're interested. As the event occurs, your handler fires, allowing you to suspend the timer and query the time elapsed, and make your increment/reset decision accordingly.
That's merely a very rough sketch of one notion, but should give you some ideas moving forward. Good luck.
Per the comment made by #hatchet above, this almost starts to sound like a queue with "expiring" members or a "sliding window" event horizon you'd have to capture should that comment accurately reflect your problem.
EDIT Being the borderline obsessive-compulsive that I am, I gave your original problem some thought and came up with a concept that may or may not be relevant to your problem, but at least for the academic exercise I'm going to post what I did. What caught my attention in your original post was the notion of an expiring or timed variable which I thought was quite novel. Your problem specified that you want to do something specific when a given interval elapses.
I tried to abstract that idea into a generic form, thinking of a few ways such an idea might be useful. One idea that came to mind was in a game environment, where (for example) a message might only be available to the player for 20 seconds before "self-destructing." I could imagine how having the expiration "plumbing" wired into a type might prove very convenient. Another scenario could be in a CAI environment where a System.Drawing.Image should only be displayed for a fixed time, then disappear - again, a scenario where having the expiration and timing code built-in could be useful.
So, with at least that much notional practicality in mind, I set to work, and what I threw together (and I won't pretend that its comprehensive or complete) is a generic for an Expiring type, expressed as Expiring<T>. The baseline code I've put together is as follows:
// First stab at an "expiring" type that is only valid for a set interval.
public class Expiring<T>
{
public delegate void ExpiredHandler(object sender, EventArgs e);
public event ExpiredHandler OnExpired;
T instance;
int signaledCount = 0;
long milliseconds = 0;
bool isExpired = false;
bool exceptOnExpiredReference = true;
System.Timers.Timer lapseTimer = new System.Timers.Timer();
public Expiring(T value)
{
instance = value;
}
public virtual void TimerElapsed(object sender, System.Timers.ElapsedEventArgs args)
{
if (OnExpired != null)
{
OnExpired(this, null);
}
isExpired = true;
}
public Expiring(T startValue, long expirationInterval, bool throwElapsedReferenceException):this(startValue)
{
milliseconds = expirationInterval;
lapseTimer.AutoReset = true;
lapseTimer.Interval = milliseconds;
exceptOnExpiredReference = throwElapsedReferenceException;
lapseTimer.Elapsed+=new System.Timers.ElapsedEventHandler(TimerElapsed);
this.Set();
}
public void Set()
{
signaledCount++;
lapseTimer.Stop();
lapseTimer.Start();
}
public T Value
{
get
{
if (!isExpired || !exceptOnExpiredReference)
return instance;
else
throw new InvalidOperationException("Reference to an expired value.");
}
set
{
instance = value;
}
}
}
The idea here is that someone could declare an Expiring<int>, specify its initial value, expiration time, and a value to indicate whether an attempt to access the value of an instance after the expiration interval has passed should throw an exception. When the expirationInterval passes, the OnExpired event is raised, allowing the declarer to specify a custom event handler to provide custom actions when the value expires.
If the caller wishes to reset the expiration timer, he need only call the Set() method of the object. That also increments an internal "signaledCount" value that I ultimately did not use, but was thinking of in terms of determining how many times the expiration timer has been reset. If the Value property of the object is accessed after the expiration interval passes, an InvalidOperationException is thrown with a "Value has expired" message.
This idea, unfortunately, has more notional/academic value than practical, I'm afraid. It would have a great deal more utility if it were possible to overload all the arithmetic operators to the implementations of the native value types, but I discovered quickly that C# doesn't like this notion at all (and found that out right here on a rather extensive post on the subject here on SO). Ideally, I'd love to be able to say something like:
Expired<Int32> foo = new Expired<Int32>(5,10000,true);
Expired<Int32> bar = new Expired<Int32>(10,10000,true);
Expired<Int32> baz = foo+bar; // can't make that work
There was some notion that this problem could be overcome with dynamic types, but I opted not to pursue it at this point. The idea, as I hammered it out, is offered for discussion as it applies to a generic view of the OP's "timed variable" notion. Constructive comments/criticism/refinements encouraged and welcome.

Related

MessageBox and while loop C#

I'm modifying existing C# code in order to pilote a piston. Every 30ms, I have a direct feedback of the position of this piston, through an event. The value is stored in a global variable I use to get the current position of the piston.
What I'm trying to achieve: for a given distance input (A->C), I want the piston to travel at full speed for 95% of the distance (A->B), and then slower for the remaining 5% (B->C).
I have access to a command that defines the speed and the destination of the piston : pos(velocity, destination).
However, if I write that code:
pos(fullSpeed,B);
pos(reducedSpeed, C);
the piston directly goes from fullSpeed to reducedSpeed
I tried to use a while loop to compare the current position of the piston with the goal destination, however, upon entering the while loop, the variable storing the piston position does not update anymore.
However, I noticed that by throwing a MessageBox in between, the position value keeps on getting updated, and I can simply click "ok" to launch the second command.
pos(fullSpeed,B);
MessageBox.show("Wait");
pos(reducedSpeed, C);
I would like to know why the "while" loop stops the update of the position variable but the MessageBox does not. I mean, as long as I don't click the "ok" button, the box is here preventing me from doing anything, which for me ressembles a while loop behaviour. Is there another way for me to do this instead of the MessageBox ?
I have little to no knowledge when it comes to C# and no support. I have tried to look in the documentation, but I did not find an answer (I have probably missed it). Any lead is more than welcome.
EDIT: I have no documentation for that code, and it is barely commented. Here is what I gathered (really hope it helps):
To move the piston, taht function is called:
MyEdc.Move.Pos(control, speed, destination, ref MyTan);
control simply define what we pilote (a distance or a load, it is an enum), and I have no idea what MyTan does. Only thing I know is that the MyEdc.Move.Pos returns an error code.
If I look at the definition of "pos", I am redirected to class
public DoPEmove Move;
containing among other things:
public DoPE.ERR Pos(DoPE.CTRL MoveCtrl, double Speed, double Destination, ref short Tan);
DoPE.ERR is also an type enum. However, I cannot reach the definition of a function named "Pos". Coud it be within the .dll included ?
The following is the code that allows me to access the position of the piston (without the global variables):
private int OnData(ref DoPE.OnData Data, object Parameter)
{
if (Data.DoPError == DoPE.ERR.NOERROR)
{
DoPE.Data Sample = Data.Data;
Int32 Time = Environment.TickCount;
if ((Time - LastTime) >= 300 /*ms*/)
{
LastTime = Time;
string text;
text = String.Format("{0}", Sample.Time.ToString("0.000"));
guiTime.Text = text;
text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_S].ToString("0.000"));
guiPosition.Text = text;
text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_F].ToString("0.000"));
guiLoad.Text = text;
text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_E].ToString("0.000"));
guiExtension.Text = text;
}
}
return 0;
}
Which is called using
MyEdc.Eh.OnDataHdlr += new DoPE.OnDataHdlr(OnData);
I realise how little I know on how the soft operates, and how frustrating this is for you. If you think this is a lost cause, no problem, I'll try Timothy Jannace solution, and if it does not help me, I'll stick with the MessageBox solution. I just wanted to know why the MessageBox allowed me to sort of achieve my objectif, but the while loop did not, and how to use it in my advantage here.
I tried to use a while loop to compare the current position of the
piston with the goal destination, however, upon entering the while
loop, the variable storing the piston position does not update
anymore.
While you are in the while loop, your app can no longer receive and process the feedback event.
One possible solution would be to use async/await like this:
private const int fullSpeed = 1;
private const int reducedSpeed = 2;
private int currentPistonPositon = 0; // global var updated by event as you described
private async void button1_Click(object sender, EventArgs e)
{
int B = 50;
int C = 75;
pos(fullSpeed, B);
await Task.Run(() =>
{ // pick one below?
// assumes that "B" and "currentPistonPosition" can actually be EXACTLY the same value
while (currentPistonPositon != B)
{
System.Threading.Thread.Sleep(25);
}
// if this isn't the case, then perhaps when it reaches a certain threshold distance?
while (Math.Abs(currentPistonPositon - B) > 0.10)
{
System.Threading.Thread.Sleep(25);
}
});
pos(reducedSpeed, C);
}
Note the button1_Click method signature has been marked with async. The code will wait for the while loop inside the task to complete while still processing event messages because of the await. Only then will it move on to the second pos() call.
Thank you for your answer ! It works like a charm ! (good catch on the
EXACT value). I learnt a lot, and I am sure the async/await combo is
going to be very usefull in the future ! – MaximeS
If that worked well, then you might want to consider refactoring the code and making your own "goto position" method like this:
private void button1_Click(object sender, EventArgs e)
{
int B = 50;
int C = 75;
GotoPosition(fullSpeed, B);
GotoPosition(reducedSpeed, C);
}
private async void GotoPosition(int speed, int position)
{
pos(speed, position);
await Task.Run(() =>
{
while (Math.Abs(currentPistonPositon - position) > 0.10)
{
System.Threading.Thread.Sleep(25);
}
});
}
Readability would be greatly improved.
You could even get fancier and introduce a timeout concept into the while loop. Now your code could do something like below:
private void button1_Click(object sender, EventArgs e)
{
int B = 50;
int C = 75;
if (GotoPosition(fullSpeed, B, TimeSpan.FromMilliseconds(750)).Result)
{
if (GotoPosition(reducedSpeed, C, TimeSpan.FromMilliseconds(1500)).Result)
{
// ... we successfully went to B at fullSpeed, then to C at reducedSpeed ...
}
else
{
MessageBox.Show("Piston Timed Out");
}
}
else
{
MessageBox.Show("Piston Timed Out");
}
}
private async Task<bool> GotoPosition(int speed, int position, TimeSpan timeOut)
{
pos(speed, position); // call the async API
// wait for the position to be reached, or the timeout to occur
bool success = true; // assume we have succeeded until proven otherwise
DateTime dt = DateTime.Now.Add(timeOut); // set our timeout DateTime in the future
await Task.Run(() =>
{
System.Threading.Thread.Sleep(50); // give the piston a chance to update maybe once before checking?
while (Math.Abs(currentPistonPositon - position) > 0.10) // see if the piston has reached our target position
{
if (DateTime.Now > dt) // did we move past our timeout DateTime?
{
success = false;
break;
}
System.Threading.Thread.Sleep(25); // very small sleep to reduce CPU usage
}
});
return success;
}
If you're using events you are probably having concurrency issues. Especially with events being raised every 30ms!
A very simple way to handle concurrency is to use a lock object to prevent different threads from using contested resources simultaneously:
class MyEventHandler
{
private object _lockObject;
MyEventHandler()
{
_lockObject = new object();
}
public int MyContestedResource { get; }
public void HandleEvent( object sender, MyEvent event )
{
lock ( _lockObject )
{
// do stuff with event here
MyContestedResource++;
}
}
}
Keep in mind that is very simple and by no means perfect in every scenario. If you provide more information about how the events are raised and what you're doing with them people will be able to provide more help.
EDIT:
Using that signature you posted for the Pos method I was able to find documentation on the library you are using: https://www.academia.edu/24938060/Do_PE
The reason you only see the method signature when you goto definition is because the library has been compiled into a dll. Actually, it probably wouldn't be that useful to see the code anyway because it looks like the library is a C# wrapper around native (c or c++) code.
Anyways, I hope the documentation is helpful to you. If you look at page 20 there are some pointers on doing movement. This is going to be a challenge for a new programmer but you can do it. I would suggest you avoid using the event handler to drive your logic and instead stick with using the synchronous versions of commands. Using the synchronous commands your code should operate the same way it reads.
I believe what you'll want to do is add a call to:
Application.DoEvents();
This will allow your application to process posted messages (events), which will allow that global variable to be updated.
I just wanted to know why the MessageBox allowed me to sort of achieve my objectif, but the while loop did not, and how to use it in my advantage here.
The reason that works is because you're giving the WndProc a chance to process events which have been sent to the application. It's not an intended feature of that call to MessageBox.Show();, but it is a consequence. You can do the same thing with a call to Application.DoEvents(); without the interruption of the message box.

How to stop function being called too often

There is a function which checks license with hardware key. But this function is getting called too often and takes time to execute. So to avoid too many call I want to check license after sometime.
bool CheckLicense()
{
if(license checked in last 10 secconds)
{
return last status;
}
else
{
hardware access for license check
return current status
}
}
Edit: Hardware key might be removed so checking once is not good practice. Also license check is to be called for enabling and disabling different button status.
In general, I think you would need something like this.
private DateTime lastCheckTime = DateTime.Now.AddDays(-1);
bool CheckLicense()
{
if (lastCheckTime.AddSeconds(10) < DateTime.Now)
return last_status;
lastCheckTime = DateTime.Now;
// hardware access for license check
return current_status
}
If you want to call it just once every 10 seconds you could use the following:
bool CheckLicense()
{
bool currentStatus = false;
//hardware access for license check
new Thread(() =>
{
Thread.Sleep(10000);
CheckLicense();
}).Start();
return currentStatus;
}
You call it once in your code and then every 10 seconds it will call itself.
Checking the licence every 10 seconds will definitely gonna add to many calls for the same function. You can do it once when the program starts as suggested in the comments whereas if it is really necessary for you to check the license or calling a function after every some time you can actually increase the timings so that you know you have checked the licence and calls will be reduced.
Like for example you checked the licence for the first time when the program starts than after that about 10 seconds and then increase the timing by 10*2 which would be 20 than next time increase it by 20*2 which becomes 40 and this will lessens the call as well as you will be checking it every few times.
bool CheckLicense()
{
timelimit = 300;
if(seconds > timetocheck)
{
return last status;
timetocheck *= 2;
if(timetocheck >= timelimit)
{
timetocheck = 10;
}
}
else
{
hardware access for license check
return current status
}
}
The program is just a prototype and doesnt mean to run directly it also does not talk about the datatypes and syntax. This is just for the understand-ability.
If You are doing this checks in sync. code, You might want to run new thread instead. And if there is problem with license, the separate thread will inform Your main thread through events:
class LicenseChecker
{
private Timer mTimer;
public delegate void LicenseNotValidDelegate();
public event LicenseNotValidDelegate LicenseNotValid;
public LicenseChecker()
{
mTimer = new Timer();
mTimer.Ticket += mTimer_Tick;
mTimer.Interval = TimeSpan.FromSeconds(10);
}
public void Start()
{
mTimer.Start();
}
void mTimer_Tick(object sender, EventArgs e)
{
if(!CheckLicense())
LicenseNotValid?.Invoke();
}
private bool CheckLicense()
{ ... }
}
...
public void Main()
{
var lLC = new LicenseChecker();
lLC.LicenseNotValid += lLC_LicenseNotValid;
lLC.Start();
}
void lLC_LicenseNotValid()
{
//code when license is not valid
}

Simple lockless stopwatch

According to MSDN, the Stopwatch class instance methods aren't safe for multithreaded access. This can also be confirmed by inspecting individual methods.
However, since I only need simple "time elapsed" timers at several places in my code, I was wondering if it could still be done lockless, using something like:
public class ElapsedTimer : IElapsedTimer
{
/// Shared (static) stopwatch instance.
static readonly Stopwatch _stopwatch = Stopwatch.StartNew();
/// Stopwatch offset captured at last call to Reset
long _lastResetTime;
/// Each instance is immediately reset when created
public ElapsedTimer()
{
Reset();
}
/// Resets this instance.
public void Reset()
{
Interlocked.Exchange(ref _lastResetTime, _stopwatch.ElapsedMilliseconds);
}
/// Seconds elapsed since last reset.
public double SecondsElapsed
{
get
{
var resetTime = Interlocked.Read(ref _lastResetTime);
return (_stopwatch.ElapsedMilliseconds - resetTime) / 1000.0;
}
}
}
Since _stopwatch.ElapsedMilliseconds is basically a call to QueryPerformanceCounter, I am presuming it's safe to be called from multiple threads? The difference with a regular Stopwatch is that this class is basically running all the time, so I don't need to keep any additonal state ("running" or "stopped"), like the Stopwatch does.
(Update)
After the suggestion made by #Scott in the answer below, I realized that Stopwatch provides a simple static GetTimestamp methods, which returns raw QueryPerformanceCounter ticks. In other words, the code can be modified to this, which is thread safe:
public class ElapsedTimer : IElapsedTimer
{
static double Frequency = (double)Stopwatch.Frequency;
/// Stopwatch offset for last reset
long _lastResetTime;
public ElapsedTimer()
{
Reset();
}
/// Resets this instance.
public void Reset()
{
// must keep in mind that GetTimestamp ticks are NOT DateTime ticks
// (i.e. they must be divided by Stopwatch.Frequency to get seconds,
// and Stopwatch.Frequency is hw dependent)
Interlocked.Exchange(ref _lastResetTime, Stopwatch.GetTimestamp());
}
/// Seconds elapsed since last reset
public double SecondsElapsed
{
get
{
var resetTime = Interlocked.Read(ref _lastResetTime);
return (Stopwatch.GetTimestamp() - resetTime) / Frequency;
}
}
}
The idea of this code, to clarify, is:
to have a simple and fast way of checking if time has elapsed since a certain operation/event,
methods should not corrupt state if called from multiple threads,
must be insensitive to OS clock changes (user changes, NTP sync, time zone, etc.)
I would use it similar to this:
private readonly ElapsedTimer _lastCommandReceiveTime = new ElapsedTimer();
// can be invoked by multiple threads (usually threadpool)
void Port_CommandReceived(Cmd command)
{
_lastCommandReceiveTime.Reset();
}
// also can be run from multiple threads
void DoStuff()
{
if (_lastCommandReceiveTime.SecondsElapsed > 10)
{
// must do something
}
}
The only change I would suggest is use Interlocked.Exchange(ref _lastResetTime, _stopwatch.ElapsedTicks); instead of Milliseconds because if you are in high performance mode it is possible to get sub millisecond results from QueryPerformanceCounter.
I would recommend creating multiple instances of the Stopwatch and only reading from it on the same thread.
I don't know what your asynchronous code looks like but in psuedo code I would do either:
Stopwatch watch = Stopwatch.Startnew();
DoAsyncWork((err, result) =>
{
Console.WriteLine("Time Elapsed:" + (watch.ElapsedMilliseconds / 1000.0));
// process results...
});
Or:
public DoAsyncWork(callback) // called asynchronously
{
Stopwatch watch = Stopwatch.Startnew();
// do work
var time = watch.ElapsedMilliseconds / 1000.0;
callback(null, new { time: time });
}
The first example assumes that DoAsyncWork work does the work in a different thread then calls the callback when completed, marshalling back to the callers thread.
The second example assumes the caller is handling the threading and this function does all of the timing itself, passing the result back to the caller.

lock-free calc: how to sum N double numbers that are changing by other threads?

upd: Let me rephrase my question shortly.
There are N double numbers. There are N dedicated threads each of them update own double number (_cachedProduct in the example below).
Somehow I need to have sum of these numbers and I need IndexUpdated event to be raised ASAP after any double number is changed (it would be nice if such event can be raised in 10 µs or less).
Below is how I tried to implement this task
===============================================
To calculate stock exchange index I create private double[] _cachedProduct; field. These field is written
by many threads
// called from another threads
public override void InstrumentUpdated(Instrument instrument)
{
if (!_initialized)
{
if (!Initialize())
{
return;
}
}
int instrumentId = instrument.Id;
OrderBook ob = Program.market.OrderBook(instrument);
if (ob.MedianOrAskOrBid == null)
{
_cachedProduct[instrumentId] = 0;
}
else
{
_cachedProduct[instrumentId] = ((double) ob.MedianOrAskOrBid)*_ammounts[instrumentId];
}
}
_ammounts is pre-initialized array and please ignore Initialize method and variable - they just works.
In loop I just sum all _cachedProduct and when values changes I notify others.
Task.Factory.StartNew(() =>
{
while(true)
{
if (_initialized)
{
break;
}
}
while (true)
{
CalculateAndNotify();
//Thread.Sleep(5);
}
}
, TaskCreationOptions.LongRunning);
protected void CalculateAndNotify()
{
var oldValue = Value;
Calculate();
if (oldValue != Value)
{
NotifyIndexChanged();
}
}
protected override void Calculate()
{
double result = 0;
for (int i = 0; i < _instrumentIds.Count(); i++)
{
int instrumentId = _instrumentIds[i];
if (_cachedProduct[instrumentId] == 0)
{
Value = null;
return;
}
result += _cachedProduct[instrumentId];;
}
Value = result;
}
I must use Interlocked to update my double _cachedProduct values but please ignore that fact now, what other problems with this code do you see?
Should I call Calculate method inside while(true) so I always use one core without delays. My machine has 24 cores so I was thinking this is ok.
However without Thread.Sleep(5) (commented) I do see significant slow-down in the program overall and I do not understand why. Program executes several dozens times slower in many places.
The question is if my idea of using while(true) without any locking at all is OK. Or should I introduce some locking method so I would only Calculate index when one of of _cachedProduct is updated?
I think you might get better performance and clearer code if you do not use an extra thread and loop for your sum. On every change to an instrument you calculate the difference and immediately update the index and perform the notify
So if a thread calls InstrumentUpdated for a single instrument;
change = newvalue - currentvalue;
// used interlocked here to change the index threadsafe
StockExchangeSum = Interlocked.Add(ref StockExchangeSum,change);
NotifyIndexChanged();
Can double[] be a more complex type?
How does WaitHandle.WaitAny compare performance wise?
Something like as follows.
private Index[] indicies;
public class Index
{
public WaitHandle Updated =
new EventWaitHandle(false, EventResetMode.AutoReset);
public double _value;
public double Value
{
get {return _value;}
set
{
if(_value != value)
{
_value = value;
Updated.Set();
}
}
}
}
TaskFactory.StartNew(() =>
{
while(true)
{
WaitHandle.Any(indicies.Select(i => i.Updated));
CalculateAndNotify();
}
});
Some points for you to think about
Have you tried profiling your calculation block in isolation to the rest of the code? I noticed this in your Calculate function:
for (int i = 0; i < _instrumentIds.Count(); i++)
_instrumentIds.Count() invokes an iteration over the entire collection and it is possible this is invoked for each trip around the loop. i.e. you are doing N^2/2 iterations of _instrumentIds
Is the _instrumentIdsIEnumerable being modified during this calculation operation? If so you could get all sorts of race conditions leading to incorrect answers.
Is the Task containing CalculateAndNotify called once or is it called many times (nested)? E.g. is there some operation inside CalculateAndNotify that could cause it to be triggered recursively?
If so, you might find you have several calculations performing simultaneously (using more than one thread until the pool is starved). Can you include some logging on start/end of operation and perhaps count the number of simultaneous calculations to check this?
If this is an issue you could include some logic whereby the CalculateAndNotify operation is queued up and new calculate operations cannot be executed until the previous has completed.

WPF: application Idle Time

I need to count the idle time of my WPF application (Idle time = when no keyboard input,mouse input (movement + clicks ) had occurred ).
So far I tried 2 approaches but none of them seem to be working:
Using the dispatcher to invoke a delegate each time it get a contextIdle priority, the problem is that binding and many other operations invoke it and thus I can't really use that.
using the input manager I registered to the "System.Windows.Input.InputManager.Current.PostProcessInput" event and each time it was invoked I restarted the idle time count.
The second approach seemed promising but the problem is that when the mouse is over the application (it has focus) I keep getting the event.
Any Other ideas? or maybe a way to modify the 2nd solution to work?
I solved the problem using a few different techniques rolled up to give me a pretty good solution. I use GetLastInput to work out when the system was last touched This is well documented elsewhere, but here's my method:
public static class User32Interop
{
public static TimeSpan GetLastInput()
{
var plii = new LASTINPUTINFO();
plii.cbSize = (uint)Marshal.SizeOf(plii);
if (GetLastInputInfo(ref plii))
return TimeSpan.FromMilliseconds(Environment.TickCount - plii.dwTime);
else
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
struct LASTINPUTINFO {
public uint cbSize;
public uint dwTime;
}
}
This only tells me when the system has been idle, not the application. If the user clicks into Word and works there for an hour, I still want a timeout. To handle this case, I simply remember when my application loses focus by overriding the OnDeactivated and OnActivated methods on the application object:
override protected void OnDeactivated(EventArgs e)
{
this._lostFocusTime = DateTime.Now;
base.OnDeactivated(e);
}
protected override void OnActivated(EventArgs e)
{
this._lostFocusTime = null;
base.OnActivated(e);
}
My IsIdle routine was added to the application object. It handles the global case where the app has focus but nothing happened (IsMachineIdle) and the specific case where the application lost focus while the user is doing other stuff (isAppIdle ):
public bool IsIdle
{
get
{
TimeSpan activityThreshold = TimeSpan.FromMinutes(1);
TimeSpan machineIdle = Support.User32Interop.GetLastInput();
TimeSpan? appIdle = this._lostFocusTime == null ? null : (TimeSpan?)DateTime.Now.Subtract(_lostFocusTime.Value);
bool isMachineIdle = machineIdle > activityThreshold ;
bool isAppIdle = appIdle != null && appIdle > activityThreshold ;
return isMachineIdle || isAppIdle;
}
}
The last thing I did was create a timer loop that polled this flag event few seconds.
This seems to work fine.
Well no one seemed to answer so I continued digging and found a relatively simple solution using the OS last input + up time. the code is really simple but this solution make me do data polling which I never recommend and also instead of being in the application level it's in the OS level which is not the exact solution I needed.
If someone ever opens this thread this is the code, just use GetIdleTime():
public class IdleTimeService
{
//Importing the Dll & declaring the necessary function
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
/// <summary>
/// return the current idle time (in ms)
/// </summary>
/// <returns>current idle time in ms</returns>
public static int GetIdleTime()
{
//Creating the object of the structure
LASTINPUTINFO lastone = new LASTINPUTINFO();
//Initialising
lastone.cbSize = (uint)Marshal.SizeOf(lastone);
lastone.dwTime = 0;
int idleTime = 0;
//To get the total time after starting the system.
int tickCount = System.Environment.TickCount;
//Calling the dll function and getting the last input time.
if (GetLastInputInfo(ref lastone))
{
idleTime = tickCount - (int)lastone.dwTime;
return idleTime;
}
else
return 0;
}
}

Categories