I need to create a method for listening to events and waiting for a certain amount of silence before calling another function.
Specifically, I am listening to a directory for file updates. When a file change occurs, my "directoryUpdate" function is called. From there I add the file to a list and create a thread called "timerThread" which sleeps for 2 seconds. When that thread is done sleeping, it calls a "gatherFinished" function.
But since directoryUpdate gets called 10 times all at once if 10 files change, it would launch 10 threads which seems like a bad way of doing this.
In the end I want a list of the file changes that occurred within 2 seconds of each other. I figure if there is a way to reset the sleep time to 2 seconds every time a change occurs and wait for the 2 seconds to finish, then I will have what I need. But there is no way to reset the timer as far as I know.
What is the best way of doing this?
UPDATE
Thanks for all your great answers. I am sorry for putting emphasis on getting the list of files. The event (file change) should not matter. I meant to focus on making sure the call to "gatherFinished" happens once at the right time - 2 seconds after all events in question have stopped firing. My question is on the nature of waiting, not on the nature of files or collections.
You could just use an AutoResetEvent and wait 2 seconds on it. If the event is triggered then you loop and wait another 2 seconds.
AutoResetEvent resetTimer = new AutoResetEvent(false);
...
private void TimerJob()
{
...
// The thread will sleep and loop until
// 2 seconds elapse without directory changes
while (resetTimer.WaitOne(2000)) {}
...
}
private void ResetTimer()
{
resetTimer.Set();
}
NOTE: I didn't put any code to specify you how to synchronize the thread that will receive the directory changes and the timer thread. You will have to do that youself.
One way of doing this would be to add each updated file to a list along with a timestamp of when they were added. Then, when your 2-second Timer fires, you can check for any items in the list that have a timestamp older than the last time it fired.
Hey Jono,
This is actually a really fun problem.
If I understand correctly you're using the FileSystemWatcher or some other similar object to monitor a folder.
Each time a file is added or changes, you receive an event.
Now the problem is that this event can be raised at relatively random times, and if you're trying to record all files which have been modified within 2 seconds of eachother, you're going to have many collections of objects.
What I would do is to create a List<List<MyFileChangeClass>> where MyFileChangeClass is whatever construct you use to track the information that changed.
When you handle the event for a file modification, create your new MyFileChangeClass with the necessary details and iterate the outer list. For each list, check to see if the first MyFileChangeClass has a time stamp of less than 2 seconds before the current file modification, if so, add your file modification to the inner list.
Once you're done walking the entire list, add a new List<MyFileChangeClass> to the outer list, which is populated with only the current MyFileChangeClass. This will ensure that future modifications can be associated with the latest one and that you have all groupings of modifications which occurred within 2 seconds of eachother.
Around the entire thing, I'd include a lock - probably a ReaderWriterLockSlim using TryEnterWriteLock().
I hope this helps - if you need more details, please let me know, but obviously you know a bit about what you're doing and probably just needed a bit of logic help because it's a strange problem.
Good luck!
Adam
I am going to assume that you are using the FileSystemWatcher class to monitor for file system changes. Your problem is well suited for the producer-consumer pattern. In your case the producer is the FileSystemWatcher which will add changed files to a queue. The consumer will then dequeue the file names from the queue once they appear. The nice thing about this pattern is that there is only one worker thread involved and all file changes will be processed in the order they are received.
Here is some code to get you started.
public class Example
{
private BlockingCollection<string> m_Queue = new BlockingCollection<string>();
public Example()
{
var thread = new Thread(Consumer);
thread.IsBackground = true;
thread.Start();
}
public void QueueChangedFile(string filePath)
{
m_Queue.Add(filePath);
}
private void Consumer()
{
while (true)
{
// The Take method blocks until an item appears in the queue.
string filePath = m_Queue.Take();
// Do whatever you need to do with the file here.
}
}
}
From the FileSystemWatcher event handlers you would call the QueueChangedFile. Add whatever code you think is necessary to process the file changes in the Consume method after the call to Take. You can make the logic as sophisticated as necessary. If you need to keep track of the time the changes occurred (so that you can later figure out which files were changed within 2 seconds of each other) then instead of having the queue hold a string you could create a simple class that stores both the file path and the change time and have the queue store that wrapper class instead.
Related
Would anyone care to explain to me how the value of this.oBalance.QouteBalance is evaluated to be true for being less than zero when it clearly isn't? Please see image below.
Am I missing something fundamental when it comes to comparing doubles in C#??
public double QouteBalance { get; set; }
UpdateBalance_PositionOpenned() is not being called in a loop, but is being called as part of a more complex event driven procedure that runs on the ticks of a timer (order of milliseconds)
EDIT: Pardon the code if it's messy but I couldn't edit it as this was a run-time error after quite a long run-time so was afraid wouldn't be able to recreate it. The Exception message is not correct and just a reminder for myself. The code after the exception is code I forgot to comment out before starting this particular run.
EDIT 2: I am building and running in Release Mode.
EDIT 3: Pardon my ignorance, but it would seem that I am in fact running in a multi-threaded environment since this code is being called as part of a more complex object method that gets executed on the ticks (Events) of a timer. Would it possible to ask the timer to wait until all code inside its event handler has finished before it can tick again?
EDIT 4: Since this has been established to be a multi-threading issue; I will try to give wider context to arrive at an optimized solution.
I have a Timer object, which executes the following on every tick:
Run a background worker to read data from file
When background worker finishes reading data from file, raise an
Event
In the event handler, run object code that calls the method below
(in the image) and other multiple routines, including GUI updates.
I suppose this problem can be avoided by using the timer Tick events to read the from file but changing this will break other parts of my code.
You're accessing shared variables from multiple threads. It's probably a race condition where one thread has thrown the error but by the time the debugger has caught and attached, the variable's value has changed.
You would need to look at implementing synchronizing logic like locking around the shared variables, etc.
Edit: To answer your edit:
You can't really tell the timer to not tick (well you can, but then you're starting and stopping and even after calling Stop you might still receive a few more events depending on how fast they are being dispatched). That said, you could look at Interlocked namespace and use it to set and clear and IsBusy flag. If your tick method fires and sees you're already working, it just sits out that round and waits for a future tick to handle work. I wouldn't say it's a great paradigm but it's an option.
The reason I specify using the Interlocked class versus just using a shared variable against comes down to the fact you're access from multiple threads at once. If you're not using Interlocked, you could get two ticks both checking the value and getting an answer they can proceed before they've flipped the flag to keep others out. You'd hit the same problem.
The more traditional way of synchronizing access to shared data member is with locking but you'll quickly run into problems with the tick events firing too quickly and they'll start to back up on you.
Edit 2: To answer your question about an approach to synchronizing the data with shared variables on multiple threads, it really depends on what you're doing specifically. We have a very small window into what your application is doing so I'm going to piece this together from all the comments and answers in hopes it will inform your design choice.
What follows is pseudo-code. This is based on a question you asked which suggests you don't need to do work on every tick. The tick itself isn't important, it just needs to keep coming in. Based on that premise, we can use a flagging system to check if you're busy.
...
Timer.Start(Handle_Tick)
...
public void Handle_Tick(...)
{
//Check to see if we're already busy. We don't need to "pump" the work if
//we're already processing.
if (IsBusy)
return;
try
{
IsBusy = true;
//Perform your work
}
finally
{
IsBusy = false;
}
}
In this case, IsBusy could be a volatile bool, it could be accessed with Interlocked namespace methods, it could be a locking, etc. What you choose is up to you.
If this premise is incorrect and you do in fact have to do work with every tick of the timer, this won't work for you. You're throwing away ticks that come in when you're busy. You'd need to implement a synchronized queue if you wanted to keep hold of every tick that came in. If your frequency is high, you'll have to be careful as you'll eventually overflow.
This isn't really an answer but:
UpdateBalance_PositionOpenned() is not being called in a loop, but is
being called as part of a more complex event driven procedure that
runs on the ticks of a timer (order of milliseconds)
see:
Multi-threading? – abatishchev 30 mins ago
Tight timer driven event-loop on the order of milliseconds probably has all the problems of threads, and will be almost entirely impossible to trouble-shoot with a step-through debugger. Stuff is happening way faster than you can hit 'F10'. Not to mention, you're accessing a variable from a different thread each event cycle, but there's no synchronization in sight.
Not really a full answer but too much for a comment
This is how I could code defensively
Local scope leads to less unexpected stuff
And it make code easier to debug and test
public void updateBalance(double amount, double fee, out double balance)
{
try
{
balance = amount * (1.0 + fee);
if (balance < 0.0) balance = 0.0;
}
catch (Exception Ex)
{
System.Diagnostics.Debug.WriteLine(Ex.Message);
throw Ex;
}
}
Value type is copied so even if then input variable for amount changed while the method was executing the value for amount in the method would not.
Now the out balance without locks is a different story.
I am working on a project where I need to let the user create one (or more) timers to fire off an event.
The user is supposed to define variables such as if the timer should be active and how often the timer will fire along with some other variables of what will happen when the timer is fiering.
All these variables are stored in a dictionary (Disctionary) where the object holds all the variables the user has set and the string is the name that the user has chosen for this timer.
I then want my program to loop through this dictionary and search for all objects which has the variable t_Active set to true (this I have already achieved).
What I need help with figuring out is the follwoing:
When it detects the variable, and if it's set to true, I need the program to see if there is already a timer created for this.
If it isn't, it should create one and set the relevant parameters for the timer.
The two variables t_num and t_period should decide the interval of the timer.
t_num is an int and t_period is a string which will be set to either minutes, hours or days.
Combining t_num with 60000 (minutes), 3600000 (hours) or 86400000 should give the corrct interval.
But how would I go on about programatically create a timer for each user-defined active object?
And how do I get the program to detect wether or not a timer has already been created?
I have been searching both here and on google, but so far I haven't come across something that makes sense to me.
I am still learning C#, so what make sense to you guys may not neccessarilly make sense to me yet. :)
I hope I have explaned what I need good enough, please do ask me to clarify if you don't get me.
Edit:
Maybe I should also mention that the mentioned dictionary will also be saved to an XML file to that the user can pick up all the settings they made at any time.
Edit 2:
#hatchet I am wondering wether or not this will work.
I have tried to make it work, but are bumping in to some difficultied (because I lack the experience and don't fully understand your pseudo-code. I am getting errors, a few that I could sovle, and a few that I couldn't. (I didn't expect fully working code, don't worry)).
Also, the user should be able to modify the timer.
In the mainform, there's a few textboxes and three buttons.
The form is used to send messages.
The user can choose to manually send their message, to add the message to a timer, or to edit the timer.
When the user hits the manual button, the messages goes out to all receivers once.
If the add the message to a timer, a new subform pops up, where they are able to set the following details:
string Name (of timer)
DateTime Start_date
CheckBox Ending
DateTime End_date
NumericUpDown Seconds (minimum value of 15 minutes)
Combobox Minutes, Hours, Days
Checkbox Active
When the user adds the message to a timer, the TimerSettings gets in to the dictionary as sting,Object (my custom object cointaing all the details).
If they hit the modify button on the main form, it is thought that before the subform is opened, the program looks for the correcponding timer (the mainform has a combobox with all added timers), stops the timer and then opens the subform to let the user edit the details.
On the subform is also a delete button so that the user can delete the timer.
When adding or modifying the timer, mainform is catching it and writes the changes to the XML file and the combobox.
And here is where it should look if there's already a timer for this message and create on of there isn't, or restart the timer if there are.
I am not sure how I should make your solution work for this though.
THe procedure of sending the messages takes anything from 30 seconds to 5 minutes depending on the number of receivers (can't be more than 42 (the program is an interface to another program which doesn't allow for more than 42 receivers)).
I understand that several timers could be an issue, but I doubt that any user would need more than max 10 timers anyway, so there could be a built in limitation of, lets say, 15 timers.
This is kind of pseudo code C#, to convey the idea. I have done this same thing, but there are enough little details that are different, that pasting that code would be confusing. So off the top of my head, this semi-code will hopefully be close enough to real code to show you what I meant by my comment to your question.
Say you have a class like this
public delegate void Work();
public class TimedThing {
public int IntervalSecs;
public DateTime NextFiring;
public event Work OnWork;
}
Then you have a controller class
public class TimedGroup {
TimedThing[] things;
System.Timers.Timer timer;
public TimedGroup() {
this.timer = new System.Timers.Timer();
this.timer.AutoReset = false;
this.timer.Elapsed += TimerFired;
}
...
// some methods for adding and removing TimerThings
...
public void Start() {
this.timer.Interval = 1; // just to get things started
this.timer.Enabled = true;
}
public void Stop() {
this.timer.Enabled = false;
}
private void TimerFired(object sender, System.Timers.ElapsedEventArgs e) {
DateTime now = DateTime.Now;
// let's have timer fire at least as frequently as every 5 minutes
// if we need to have it fire sooner than that, it will get set below
DateTime next = now.AddMinutes(5);
foreach(var thing in this.things) {
if (thing.nextFiring <= now) {
var task = Task.Factory.StartNew(() => DoWork(thing));
thing.NextFiring = thing.NextFiring.AddSeconds(thing.IntervalSeconds);
// or maybe this is more appropriate
// thing.NextFiring = Now.AddSeconds(thing.IntervalSecs);
}
if (thing.NextFiring < next) next = thing.NextFiring;
}
// set the timer to fire whenever the next soonest work needs to be done
this.Timer.Interval = (next - now).TotalMilliseconds;
this.Timer.Enabled = true;
}
private void DoWork(TimedThing thing) {
thing.Work();
}
}
There are likely details though that have to be dealt with, although many of these details have to be dealt with whether you are using a timer for every thing, or a single timer for them all. For instance, what if the work for a thing normally takes 10 seconds, but occasionally it may take 60 seconds, and they have a time interval set for 45 seconds. Sometimes the next firing will want to run that work again, although the previous work started on the previous firing is still running. That may or may not be desirable, depending on what kind of work these things are doing. If it isn't desirable, you have to add some monitoring of the tasks that get spawned so you will know if you need to skip doing the work because the previous work isn't done yet. Another thing is coding a graceful winding down. When you set the timer.Enabled to false (or timer.Stop()...which is the same thing), there is a brief period of time where the timer event can still fire, even though you stopped the timer (see Why does System.Timer.Timer still fire events when Enabled is set to false?). That can make for some weird behavior/bugs.
I'm not sure how well timers will scale with that approach. It might be worth investigating other approaches to managing these events. As #hatchet just made a comment, you could have 1 timer for the next event.. with that approach, you can set up the next one when it runs.
Another possibility is using a database and a timer that runs every <small time period> which executes all actions with due time stamps.
here i have written a window service, it job is to read files from one folder and sending the same content to database and sending readed files to some other folder
now my service having timer event has sets it was about of 10000 means ten seconds,
now if a process a files between 100 - 1000 ,with in 10 sec it was doing that job processing good output, case if process the files 6000 - 9000 at that particular situation my service is not producing exact out, it was not able to do that job in 10000 (ten seconds), so i need when service in middle of the job it should get interrupted since by timer completed but real scenario it should completed the particular job.
kindly give some suggestions, it would be appreciated
Different approaches that can work:
Have the method called by the timer safe for re-entrance and then not worry about it. This tends to be either very easy to do (the task done is inherently re-entrant) or pretty tricky (if it's not naturally re-entrant you have to consider the effects of multiple threads upon every single thing hit during the task).
Have a lock in the operation, so different threads from different timer events just wait on each other. Note that you must know that there will not be several tasks in a row that take longer than the time interval, as otherwise you will have an ever-growing queue of threads waiting for their chance to run, and the amount of resources consumed just by waiting to do something will grown with it.
Have the timer not set to have a recurring interval, but rather re-set it at the end of each task, so the next task will happen X seconds after the current one finishes.
Have a lock and obtain it only if you don't have to block. If you would have to block then a current task is still running, and we just let this time slot go by to stay out of it's ways.
After all, there'll be another timer event along in 10 seconds:
private static void TimerHandler(object state)
{
if(!Monitor.TryEnter(LockObject))
return;//last timer still running
try
{
//do useful stuff here.
}
finally
{
Monitor.Exit(LockObject);
}
}
Use a static boolean variable named something like IsProcessing.
When you start working on the file you set it to true.
When the timer is fired next check if the file is still in processing.
If it's still processing, do nothing.
Good morning,
At the startup of the application I am writing I need to read about 1,600,000 entries from a file to a Dictionary<Tuple<String, String>, Int32>. It is taking about 4-5 seconds to build the whole structure using a BinaryReader (using a FileReader takes about the same time). I profiled the code and found that the function doing the most work in this process is BinaryReader.ReadString(). Although this process needs to be run only once and at startup, I would like to make it as quick as possible. Is there any way I can avoid BinaryReader.ReadString() and make this process faster?
Thank you very much.
Are you sure that you absolutely have to do this before continuing?
I would examine the possibility of hiving off the task to a separate thread which sets a flag when finished. Then your startup code simply kicks off that thread and continues on its merry way, pausing only when both:
the flag is not yet set; and
no more work can be done without the data.
Often, the illusion of speed is good enough, as anyone who has coded up a splash screen will tell you.
Another possibility, if you control the data, is to store it in a more binary form so you can just blat it all in with one hit (i.e., no interpretation of the data, just read in the whole thing). That, of course, makes it harder to edit the data from outside your application but you haven't stated that as a requirement.
If it is a requirement or you don't control the data, I'd still look into my first suggestion above.
If you think that reading the file line by line is the bottleneck, and depending on its size, you can try to read it all at once:
// read the entire file at once
string entireFile = System.IO.File.ReadAllText(path);
It this doesn't help, you can try to add a separate thread with a semaphore, which would start reading in background immediately when the program is started, but block the requesting thread at the moment you try to access the data.
This is called a Future, and you have an implementation in Jon Skeet's miscutil library.
You call it like this at the app startup:
// following line invokes "DoTheActualWork" method on a background thread.
// DoTheActualWork returns an instance of MyData when it's done
Future<MyData> calculation = new Future<MyData>(() => DoTheActualWork(path));
And then, some time later, you can access the value in the main thread:
// following line blocks the calling thread until
// the background thread completes
MyData result = calculation.Value;
If you look at the Future's Value property, you can see that it blocks at the AsyncWaitHandle if the thread is still running:
public TResult Value
{
get
{
if (!IsCompleted)
{
_asyncResult.AsyncWaitHandle.WaitOne();
_lock.WaitOne();
}
return _value;
}
}
If strings are repeated inside tuples you could reorganize your file to have all different involving strings at the start, and have references to those strings (integers) in the body of the file. Your main Dictionary does not have to change, but you would need a temporary Dictionary during startup with all different strings (values) and their references (keys).
How can I have a WinForms program do some specific thing whenever a certain time-based condition is met?
I was thinking I could do something with two threads, where one thread runs the normal program, and the other thread merely loops through checking if the time-based condition is true yet or not, and when the condition is true it signals an event.
However I am unsure of the best way to do it. Where in the program would I call the two threads? Maybe I am thinking about it all wrong?
How would you do this?
MORE INFO:
What it has to do is check the data.dat file and see when the last time it was updated was. If it was a month or more then do the specific thing. Could this still be done with a Timer?
NOTE:
I think it might be useful to note the difference between the System.Timers and the System.Windows.Forms.Timer...
I think you should use a Timer set to an inteligent interval to check if your time-based condition is met.
It depends what your time-based condition is. Is it a special time or an interval after which you want to do something special? If it's the second, you can just use the Timer and do what you have to do when the Timer.Elapsed event is fired.
Edit after your edit:
If you want an event to be fired every time the file changes, use a FileSystemWatcher
Edit2:
Here's the difference between System.Windows.Forms.Timer and System.Timers:
The Windows Forms Timer component is
single-threaded, and is limited to an
accuracy of 55 milliseconds. If you
require a multithreaded timer with
greater accuracy, use the Timer class
in the System.Timers namespace.
You could add a System.Windows.Forms.Timer control to your Form (see the Components category in the toolbox).
Then set the timer's interval to some value (e.g. 1000) and add a handler for its Tick event. This handler will then be called once every 1000 milliseconds.
In the handler you can then check if the conditions are met and if yes, start your specific operation.
Update (after you updated the question):
To check if the last modification of a file was more than one month ago, you can use this code:
if (File.GetLastWriteTime("data.dat").AddMonths(1) < DateTime.Now)
{
// do whatever has to be done
// if it is a time-consuming task, start a new thread!
}
You can still put this into the Tick event handler of the timer component. But in that case it does probably not make sense to fire the timer every second.
Depending on your application (e.g. if it will be started quite often), another possibility would be to execute the above check during the startup of your application.
Regarding your 'more info':
How many times must it check the modification-date of that specific file ?
Only once (during startup for instance), or should it check the modification-date of that file multiple times during application execution ?
If it has to be done only once, then it is useless to use a timer.
If it has to be done multiple times, then yes, you could use a timer.
The eventhandler of the Elapsed event could then check the ModificationDate of the file, and see if action needs to be taken.
Another solution, which is probably more elegant, is using a FileSystemWatcher.
This FileSystemWatcher could 'watch' that particalur file.
Specify a Filter on the FileSystemWatcher so that, every time the particular File is changed, an event is raised.
In the eventhandler of the FileSystemWatcher, you can then take the necessary action:
FileSystemWatcher dataFileWatcher = new FileSystemWatcher();
dataFileWatcher.Path = "path to your file";
dataFileWatcher.Filter = "yourfilename";
dataFileWatcher.Changed += new FileSystemEventHandler(OnFileChanged);
dataFileWatcher.NotifyFilter = NotifyFilters.LastWrite;
dataFileWatcher.EnableRaisingEvents = true;
private void OnFileChanged( object sender, FileSystemEventArgs e )
{
// take action.
}
Note however, that there's a sublte bug / feature in the FileSystemWatcher which causes that the Changed event gets raised multiple times for one change to the File you're watching.
You can resolve this like this
Another alternative, if you know the time between file updates (a month) is to check once at startup time. If the file is out of date you can process it immediately. If not, you can then work out how long you need to wait before checking it again. You can then schedule a task using a wait timer or other methods as described in the answers.
Basically, at startup time you can find out the limit/worst case on how long you have to wait and then you don't need to do any additional checks in the meantime. This assumes of course that the file can't be changed to an OLDER version during the running of the program which seems unlikely, but not impossible!