I will try to make the question as simple so that it is easy to get an idea of the scenario. I am trying to build a stock related application for school project, which is fetching data from the web for a particular stock. So the user inputs stock name in a text box and after clicking the button, the name of the stock is passed to the method downloading data for that particular stock. Now i want that method to be called on every second for the same stock so that user can get the latest updates. Till now no problem. But when the user wants to monitor more than one stocks, i need to dive into threading. As for each stock there will be a thread will be calling the update stock method every second. So for example there are 5 stocks so there should be 5 threads that are working simultaneously calling the method every second to update the results. I hope i have made the problem clear to understand.
To accomplish this i am using the System.Threading.Timer in the button click event and it is calling the method for stock update. But the problem is that when i enter the first stock the method is called only 2 times, for the second stock it is being called for 6 times and for 3rd stock more than 12 times. What is the reason behind such weird behavior.
Any idea if there is any other way around to achieve what i am trying to do.
Following is the code i am working on.
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.Rows.Add("","","","","","test", "test");
int i= dataGridView1.Rows.Count - 1;
string stock = textBox1.Text + ":"+i;
System.Threading.Timer tmr = new System.Threading.Timer(Tick,stock,1000,2000);
}
public void Tick(object stock)
{
lock (locker)
{
string maindata = stock.ToString();
string[] testing = maindata.Split(':');
byte[] data = null;
Uri uri = new Uri("some url where i am getting data from");
WebClient wc = new WebClient();
wc.DownloadDataCompleted += delegate(object sender, DownloadDataCompletedEventArgs e)
{
data = e.Result;
};
wc.DownloadDataAsync(uri);
while (wc.IsBusy)
{
Thread.Sleep(100);
}
string strData = Encoding.ASCII.GetString(data);
string[] s = strData.Split('{');
string data1 = s[4];
string[] data2 = data1.Split('}');
string final = "[{" + data2[0] + "}]";
Form1 obj = new Form1();
List<Form1> jarray = JsonConvert.DeserializeObject<List<Form1>>(final);
dataGridView1.Rows[System.Convert.ToInt32(testing[1]) - 1].Cells[0].Value = jarray[0].Symbol;
dataGridView1.Rows[System.Convert.ToInt32(testing[1]) - 1].Cells[1].Value = jarray[0].Ask;
dataGridView1.Rows[System.Convert.ToInt32(testing[1]) - 1].Cells[2].Value = jarray[0].Volume;
dataGridView1.Rows[System.Convert.ToInt32(testing[1]) - 1].Cells[3].Value = jarray[0].Bid;
}
}
Since with every click you are creating a new Timer. This will mean with every subsequent click, more timers will respond so you start getting the events twice, 4 times, ....
Move this line out of click and put it in the initialization of the form:
System.Threading.Timer tmr = new System.Threading.Timer(Tick,stock,1000,2000);
This does not mean I fully approve your approach since that has nothing to do with the question you are asking.
I suggest you look at Asynchronous Programming Using Delegates. On every tick (using just 1 timer) you should launch a delegate asynchronously to get your values for each stock the user requests.
"But when the user wants to monitor more than one stocks, i need to dive into threading". Not true. Now I don't want to spoil a perfectly good opportunity to dive headfirst into threading, but you don't need to here. Why not refresh all stocks at the same time?
So each time the timer ticks, you download the prices for all the stocks in one go. If you have control of the serverside interface (where you get the data from), make a method that accepts a collection of stocktickers and returns a collection of stockprices. If the server only returns one at a time, you get them on by one in a loop.
Also when you really want to have something that responds quickly, don't poll for new prices every second but have the server notify you when something has changed by subscribing to an event for instance. Some stocks will not move for minutes, while other move very quickly. For most trading purposes, a full second is a lifetime. If you're on WPF, look into DataBinding and INotifyPropertyChanged. That fits extremely well for this type of problem.
GJ
#Prashant - Obviously your approach is not correct. What you actually want to happen is to have multiple threads which will tick at different intervals. As Aliostad hinted at your approach isn't correct.
System.Threading.Timer is a simple,
lightweight timer that uses callback
methods and is served by thread pool
threads. It is not recommended for use
with Windows Forms, because its
callbacks do not occur on the user
interface thread.
System.Windows.Forms.Timer is a better
choice for use with Windows Forms. For
server-based timer functionality, you
might consider using
System.Timers.Timer, which raises
events and has additional features.
What I would do is use a mutex approach to determine if a new thread is required. I would pass the name of the stock and within the thread itself start the timer. If you wanted to a feature to "pause" or "stop" a stock from being watched would be easy enough.
The current class your using is threaded your approach itself is flawed.
As for each stock there will be a thread will be calling the update stock method every second. So for example there are 5 stocks so there should be 5 threads that are working simultaneously calling the method every second to update the results. I hope i have made the problem clear to understand.
Except this isn't what you are doing. What you are actualy doing is starting a new timer thread for each time the button is pressed( for every stock ) which of course is NOT what you actually want to do ( based on your own statements ).
Related
I am writing a "game" simulating Student's Adventures at The University and what I have done already is few forms, still I need one form to not wait for user input but check if I want an Game Event to run now, if not, then wait few seconds and then skip to another day and repeat the procedure for that day.
The thing is user is able to quit the game at any time and all the information is saved so I need to keep it an one-shot timer of few seconds that doesn't run for another time after it expires.
How do I write an one-shot timer or delay an execution of my c# code for few seconds?
EDIT:
MessageBox.Show("I will wait 3 seconds now");
wait 3 seconds
...
after 3 seconds
MessageBox.Show("3 seconds passed since I poped out last message box!");
If all that you want to do is create a method to "tick" every so often, there are a few options.
The first would be the System.Threading.Timer object, documented on MSDN here: http://msdn.microsoft.com/en-us/library/system.threading.timer%28v=vs.110%29.aspx
An example of this:
public void Tick(object stateInfo /* required to fit TimerCallback signature */)
{
/// add your code here
}
And your Timer instantiation would look like so:
System.Threading.Timer timer = new System.Threading.Timer(Tick, null, 0, 3000);
And thereafter Tick() will be executed every 3 seconds. Feel free to replace the null with an object of your choice so as to keep track of state.
A second, worse choice would be to use a BackgroundWorker. The primary advantage I've found in this is that the ProgressChanged event handler is automatically invoked in the primary UI thread, so you can use it fairly easily for cross-thread code that involves the UI in some sense. Here's the documentation on MSDN: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker%28v=vs.110%29.aspx
I don't think the BackgroundWorker would be a good choice - it's user-friendly, but it's not really designed to persist infinitely, or activate periodically, so its usage leads to bad workarounds like wrapping all the DoWork code in a while(true) loop and using Thread.Sleep() to pause execution.
A third would be the System.Timers.Timer object, which takes an Interval in milliseconds and an Elapsed event hooked into one of your methods. Each time the interval passes, your method is called. The documentation for that is here: http://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.110%29.aspx
Note that all of these work slightly differently, so one may well fit your use case significantly better. We can't really tell you which one is best because we don't really know much about your implementation right now.
http://msdn.microsoft.com/library/system.threading.timer.aspx
static void Main(string[] args)
{
Timer tmr = new Timer(S, null, 0, 5000);
Console.Read();
}
static void S(object obj)
{
Console.WriteLine("1");
}
and u can look here
Execute a method after delay on time only
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.
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.
I have an app that crawls a network looking for movies, their titles, length and last accessed time. Since there are a lot of computers on the network, this can take awhile and I would like to update my listview in real time. Heres what I have so far but its not working at all.
private void PopulateListView()
{
this.listView1.SuspendLayout();
listView1.Items.Clear();
// go thru list of movies to add
foreach (string movie in listviewMovieList)
{
ListViewItem item1 = new ListViewItem(movie);
listView1.Items.AddRange(new ListViewItem[] { item1 });
}
this.listView1.ResumeLayout();
}
This gets called by my background workers ProgressChanged method:
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string movie = (string)e.UserState;
if (movie != null)
{
listviewMovieList.Add(movie);
PopulateListView();
}
this.progressBar1.Increment(e.ProgressPercentage);
}
The problem is that it isn't slow enough. You are calling ReportProgress() too often. It depends on how much work the UI thread does, but do it roughly several hundred times per second and the UI thread freezes, not getting around do doing its normal duties anymore. Like painting the list view. Your code is very expensive, clearing and repopulating the ListView requires lots of Windows messages.
At least don't do it for one movie at a time, batch it up and use the AddRange() method. One call per 50 msec is ideal, a human cannot read any faster than that anyway. Slow down the worker thread by using Invoke() instead of BeginInvoke(). ListView.VirtualMode can help.
I think the issue might be to cross thread calls to WinForm UI controls.
Take a look at
Control.InvokeRequired Property
Gets a value indicating whether the
caller must call an invoke method when
making method calls to the control
because the caller is on a different
thread than the one the control was
created on.
and Control.BeginInvoke Method (Delegate)
Executes the specified delegate
asynchronously on the thread that the
control's underlying handle was
created on.
I have a fairly process intensive method that takes a given collection, copies the items(the Item class has its Copy() method properly defined), populates the item with data and returns the populated collection to the class's collection property
//populate Collection containing 40 items
MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems );
This method is called in two ways: upon request and via a System.Timers.Timer object's 'Elapsed' event.
Now 40 items in the collection take almost no time at all. Whether being populated 'ad hoc' by say a button_click or populated by the Timer object.
Now when I increase the size of the collection (another MyClass object that has 1000 items), the process predictably takes longer, but around 6sec in total.
That's fine, no problems there. Being called upon initialization (form_load) or being called ad hoc (button_click) it stays around 6sec.
//populate Collection containing 1000 items
MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems );
But, the SAME METHOD (as in the exact line of code) is being called by the System.Timers.Timer object. And that Elapsed takes around 60 seconds (other runs unclide 56sec, 1min 2Sec, 1min 10 sec... you get the idea).
Ten times as long for the same process!
I know the System.Timers.Timer object is executed in the Thread-pool. Could this be the reason? Is the thread-pool given lower priority or is the whole queuing thing taking up the time?
In short, what would be a better approach to this? Using the System.Windows.Forms.Timer to execute in the same UI thread?
Thanks!
Ok, some additional info:
The timer operation is occurring within a DLL being called by the UI. The main 'handler' class itself has a collection of timer objects all subscribing to the same event handler.
The handler class' initialization works kinda like this:
UpdateIntervalTimer tmr = new UpdateIntervalTimer(indexPosition);
tmr.Interval = MyClass.UpdateInterval * 60000; //Time in minutes
tmr.Elapsed += new System.Timers.ElapsedEventHandler(tmr_Elapsed);
this.listIntervalTimers.Add(tmr);
I've actually inherited the Timer class to give it an 'index' property (The eventArgs as well). That way within one event handler (tmr_Elapsed) i can identify which MyClass object the timer is for and take action.
The handler class is already running in a thread of its own and fires a custom event to give insight to its operations.
The event is handled in the UI (cross-threading access of UI controls and whatnot) and displayed with the time recievedthe event is handled. This is true for both 'initialization' and 'ad hoc' calls (there is no problem in those cases).
The actual Elapsed event looks as follows:
private void tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
UpdateIntervalTimer tmr;
tmr = (UpdateIntervalTimer)sender;
MyClass c = listOfClasses[tmr.IndexPosition];
observerEventArguments = new MyHandlerEventArgs("Timer is updating data for " + MyClass.ID);
MessagePosted(this, observerEventArguments);
try
{
//preparation related code
MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems);
observerEventArguments = new ProfileObserverEventArgs(MyClass.ID + ": Data successfully updated");
MessagePosted(this, observerEventArguments);
}
catch (Exception exUpdateData)
{
observerEventArguments = new MyHandlerEventArgs("There was an error updating the data for '" + MyClass.ID + "': " + exUpdateData.Message);
MessagePosted(this, observerEventArguments);
}
}
Well, the UI thread is likely to have a higher priority - after all, it's meant to keep the UI responsive. However, there are other things that could be going on. Does your method access the UI in a thread-safe manner? If so, obviously it's going to be faster when it doesn't need to marshall between threads.
You could try boosting the priority of the thread-pool thread to see if that improves performance - but apart from that, we'll need more info.
I wouldn't advise you to do this on the UI thread - hanging the UI for 6 seconds doesn't make for a nice user experience :(
Is the interval elapsing while you're still doing work in the timer, causing it to do the same work multiple times? That's the only reason I can think that the UI timer works faster than the system.timers.timer/system.threading.timer, since the UI timer is single threaded and cannot elapse again until it's finished, while the others can.