I am new to the world of GUI programming and I am writing a little GUI app using IronPython and WinForms. It reads values from an external device and displays them in a ListView component (name, value). I want to periodically perform the reading and updating of the ListView component at a certain fixed rate.
I had the following ideas to accomplish this:
A timer, which periodically triggers the read/screen update directly in the OnTick handler
A timer, whose OnTick handler triggers a BackgroundWorker to perform the read/update
Since the first solution will block the GUI until the read/update loop is done, which, depending on the number of values being read from the device, could take some time, I think the BackgroundWorker might be a better solution. I might want to add some functionality to manipulate the ListView items later (add, remove values etc.) and a blocked GUI does not seem like a good idea.
Is there a certain design pattern or a better way to accomplish reading/updating screen data?
NOTE: Any code examples can be IronPython or C#. The conversion from C# to IronPython is pretty straight forward. Thanks!
Personally, I'd have one thread that's responsible for reading values out of the device and storing the data in a data structure, and then a System.Windows.Forms.Timer (there's 3 Timers in .NET, this is the only one that ticks in the thread that's safe to update your controls) to read values out of that data structure and update the UI. You may need to synchronise that data structure, you may not.
That way the device can take as long as it likes to return data, or it can push as many millions of rows per second at you, and the UI thread will still poll at your predetermined tick rate (probably every 100 msec?). Since your timer ticks are just reading data out of memory, the UI won't block for IO.
The BackgroundWorker is prefered when you have lot of work to do in the background.
Use a Timer to trigger a function that will do the necessary work in a second thread.
It won't block the UI. (don't forget to update the controls on the UI thread).
System.Threading.Thread newThread;
newThread = new System.Threading.Thread(anObject.AMethod);
http://msdn.microsoft.com/fr-fr/library/ms173178(VS.80).aspx
Another option rather than getting the Timer and the Background worker thread working would be to use the System.Threading.Timer, this will execute your method on a thread on a regular interval and once you have the data you can use Control.Invoke or Control.BeginInvoke to update the control in the UI thread.
Related
I should report several certain things to my GUI while another thread is running in the background, such as:
Progress Value
Elapsed Time
Number of Results Found in real-time
Number of Errors Occurred during the process
and so on
I can use this piece of code when I need to invoke the UI and change something:
private void DoInvoke(Action action)
{
try
{
if (InvokeRequired)
BeginInvoke(action);
else
action();
}
catch { }
}
It works well, GUI and background thread work very well and the info will be reported and shown in UI.
But there is a problem, because of so many contexts changing between the background thread and UI, the CPU usage will be very high! I need to update the UI values without this context changing and without CPU usage.
So I decided to make a class of needed values and send it to the background thread. so It is a reference in which both UI and background thread can access it.
and I have put an event handler inside the class, so whenever a value is changed it will invoke. in UI I have attached an event to this handler, so every time a value is changed in this class, the UI should update that value. But again I will face cross-thread error. How to handle such a thing? I do not want the high cpu usage and also I need real-time UI update.
There are various ways to approach this.
The first thing is to define "realtime". If your data changes every 1 millisecond, even if you were able to update the UI that fast, noone would be able to see it. As a guideline, we can only detect changes at around 60Hz (that's why videogames target that framerate). In practice, you probably want the UI to update in the 10-50Hz range.
The timer solution
A simple solution, which may or may not be appropriate, would be to setup a timer on the UI thread that fires at the appropriate rate and update your controls in the timer event handler.
The Invoke() / BeginInvoke() solution
Another option is to still use the BeginInvoke() approach, but:
Implement the logic to update all controls in a single function and only BeginInvoke() that one, so you only queue a single work item in the UI thread. If you were to do a BeginInvoke() for each control, you'd cause a context switch for each control.
Skip invoking a BeginInvoke() if a minimum time has not elapsed since the last update. For instance, if data has changed after 3 milliseconds, you could skip all updates until one happens after 50 milliseconds (that would give a max update rate of 20 Hz).
The complications
This will work fine if you have simple controls, however you could run into issues if you have complex ones, like graphs, of many many controls to update. In this case, it may take a long time to redraw them, so you could not be able to update the UI at the desired rate. In you BeginInvoke() too often and the UI thread can't keep up, the app will essentially freeze because it doesn't have time to handle the user input.
There could be other conditions that lead the main thread to be more busy than usual (resizing the window or other processing that takes max a couple of seconds and you didn't bother to run in a separate thread).
So, in my programs, I usually set a flag immediately before I call BeginInvoke(), and I clear it in the invoked function. The next time I have to call BeginInvoke(), I first check the flag. If it's still set, it means the UI thread was busy and still hasn't managed to update the UI. In that case, I skip the BeginInvoke().
Finally, if you have a lot of stuff going on (I had to update many graphs and views) you may also need to have your logic guarantee a minimum time from when the update code in the UI thread ends executing and when you queue a new update from your background thread. This guarantees there's some time left in the UI thread to process user input, while the thread is very busy updating the UI in the rest of the time.
Final notes
If a value has not changed, you want to avoid redrawing the relative control, because it's pointless. I expect most WinForms controls, like a label, to already not redraw if you set their Text to the same value they already have, but if you have custom controls, third party controls, or do things like clear a ListView and repopulate it, you want to make sure the code isn't causing a redraw when it's not needed.
I'm new to C# and I'm doing a project needs two timer to access the same variable at the same time.(one to read and other one to write or update).So, my problem is which Timer should I use? Forms.Timer or Thread.Timer. I've read some article about their difference. Since I want to use these timers to update the Interface of the program (image in picture box), So I think Forms.Timer should be used here since it's related to GUI stuff. However, the order that which timer executes first is also matter, so I think Thread.Timer should also be considered. Is there any way I can combine them together?
Update: I'm doing a ECG project, so basically I'm keeping receiving data and I want to draw them on the form. however, since drawing took about 40 ms, so using one timer would have delay but I need real time.(For example, If I set the interval to 100 ms, then It took 140 ms to finish one frame drawing that should be finished in 100 ms. This will cause 40 ms delay for every tick. ) Therefore, My solution is using one timer to update the data buffer when I received the data, and use other timer to call Invalidate, which would repaint all the new data. Should I use thread.timer to do the updating of data and form.timer to redraw the form?
The main difference between both timers is that the Form.Timer works in the same thread as your Form, so there is no problem in accessing or changing state of any GUI component (control etc.) by Tick event handler code. In case of Thread.Timer, there is no guarantee that the TimerCallback method is called from current thread (can be, but not must be), so accessing the GUI components can be slightly hard and not easy (you have to use Invoke(), like here: Accessing a form's control from a separate thread). On the other hand, any long-term and intensive processing, implemented in Form.Timer.Tick handler will be executed in same thread as GUI, so it can degrade GUI efficiency and responsibility. So, the general rule is: for fast, short-term operations on GUI components, use Form.Timer, and for long-term, heavy computations, not requiring access to GUI components, use Thread.Timer. Of course, it is simplified rule - the final decision should depend to specific case.
I have a RichTextBox that the Console is redirected to. The Console Redirector delegates the AppendText() call each time the console is written to. However, the GUI locks up while the text is being appended, and since the log is written to in periods of rapid succession, the main thread/GUI locks up until the text is no longer being appended. Is there a way to allow control of the form while the log is being appended from another thread?
No, you cannot safely update the UI from a non-UI thread.
If you have other UI work that you want done you'll need to have your console redirect function simply spend less time updating the UI. Don't have it update the UI with everything all the time. Have it buffer the data and write to the UI less frequently, or throttle the console input if there is simply too much data to display everything (while also doing other necessary work).
All in all, no you cannot get away from the lockedness. The UI thread will be locked when working, and when you dispatch to it you are in essence saying, I want to run this piece of code on the UI thread.
To alleviate some of the "lockedness" you need to try to be "smart" about it.
Update as rarely as possible to manage this, use some sort of "buffer" to update. Possibly make a "fake" UI class (aka a model/DTO) fill it with data from your thread and flush it out to the UI when needed/on demand/on complete
In the delegates as much as possible. DO NOT perform any form of logic as that's work that will lock you for a longer period than needed.
I see that you are using winforms, if this is a project where you are in control, then go for WPF.
I would like to ask what method to update GUI is better for my scenario.
I would like to manipulate (move) multiple controls from point to point based on the input from user's touches.
I know a few difference way to do it.
Dispatcher Timer & Timer. (What's the difference between them?)
BackgroundWorker.
Storyboard & BeginAnimation Method.
Which of these method is generally recommended to use in term of memory and resource saving and simpler to code?
Thank you!
I suppose these 3 SO QA should help u understand all the differences:
DispatcherTimer vs a regular Timer in WPF app for a task scheduler
Comparing Timer with DispatcherTimer
WPF BackgroundWorker vs. Dispatcher
Apart from the link given by Vijay, a common concept that is vital in WPF application while you manipulate visuals is Dispatcher
In short, a Dispatcher is a message queue gateway manager to the UI, that receives delegates and prioritises them to execute on the given thread. In WPF, UI thread is STA. Also any visual created on UI thread has a thread affinity which means if you are performing any multi threaded functionality (for faster performance) then when it comes to manipulating those visuals such as updating their values, increasing / deacresing their size, focusing them, transforming them etc. has to be done using the UI Dispatcher.
Now back to your situation, when you want to move items, translate transform animation is a good option.
Hope this helps you in correct direction.
I have a C# app that receives updates from a server, processes it, and updates the GUI. the updates come in constantly, say several times a second. I want the app to update the GUI at most once every 2 seconds. so if an update comes in at time T, I want all updates that come in from T through T+2sec to stay in a buffer, and at T+2sec do the processing and GUI update. I know in JS you can use setTimeout() to execute some code at some time in the future, so I want something like that.
what's an appropriate way to do this? I've heard that using threads to "schedule" a function call isn't a great idea, but I'm not sure of a better way to do this. would it be so bad to use a Timer with a two second interval, synchronized to the GUI thread, that does the processing/updating?
You can use a System.Windows.Forms.Timer. It doesn't run events in a separate thread, it's the GUI thread that runs them. That way you can update the GUI directly without having to use Invoke.
You should use one of the timer classes, as you posted in your question.
See this MSDN article comparing them - this should give you a good basis to make a decision.