Update GUI while Other Threads are working without Thread Change - C# - c#

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.

Related

Avoiding main thread lockup when delegating to GUI

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.

Why does the UI thread hang when updating list in background?

I thought I had a pretty good handle on threading until I came across a scenario in which I wanted to benchmark updates to different grids.
I created a window with a grid control, bound an ObservableCollection to it and populated it with 5000 rows of some complex data type (which contains no locks).
Then I created a task using
Task.Factory.StartNew()
This went through a very tight loop (10 million iterations) updating a random property on a random item in my ObservableCollection, each of which raises an INotifyPropertyChanged event of course.
Now since the updates are all happening on the background thread I expected the UI to update, albeit hard-pressed to keep up with this background thread spinning in a tight loop.
Instead the UI froze for several seconds (but didn't go blank or produce the usual spinning cursor of doom) and then came back once the background thread finished.
My understanding was that the background thread would be taxing a core pretty heavily while producing tons of INPC's, each of which get marshalled automagically by the WPF runtime to the UI thread.
Now the UI thread is doing nothing so I expected it to consume all these INPC's and update the grid but it didn't; not a single update occurred. However, when I do this using a Timer (instead of a tight loop) it works fine.
Would someone please enlighten me as to what the heck the UI thread is doing? Thanks in advance!
If you clog up the message pump with a lot of dispatched updates like this, other messages won't get a chance to be processed, which causes the 'freeze' effect you observe.
One thing that can help here is to use Data Virtualization on your UI control so that only the visible rows are actually bound and listening to INPC updates. This is turned on by default for DataGrid, but if you're using a more custom approach to visualizing the data, this could be an issue.
That said, this won't help with frequent modifications to items that are currently visible, as truly rapid fire updates will still clog up the dispatcher. If you have a use case like this, you probably want to isolate your view model objects a bit and have a way to 'batch' your updates. One technique is to have a way to suppress notification while you do a bunch of updates, then call RaisePropertyChanged(null) (or whatever equivalent method on your INPC helper base class) on each instance to update all bindings to that instance.
Another mechanism is to make the data updates in some other layer (whatever model object(s) your view model instance is representing), then copy over those properties to the view model class at well-defined intervals. For rapidly updating background data, I often use a polling loop rather than triggering on events, simply because the events would occur more frequently than the UI cares about and it slows down the background processing to send all these unnecessary notifications constantly.

Alternative to Thread.Sleep that keeps the UI responsive?

I'm doing all this in C#, in Visual Studio 2008.
I want to slow down the work of my algorithm so that the user can watch it's work. There is a periodic change visible at the GUI so I added Thread.Sleep after every instance.
Problem is that Thread.Sleep, when set to at least a second, after a few instances of Thread.Sleep (after few loops) simply freezes entire GUI and keeps it that way till program completion. Not right away, but it always happens. How soon depends on the length of the sleep.
I have proof that entire program does not freeze, it's working it's thing, even the sleep is making pauses of correct length. But the GUI freezes at certain point until the algorithm ends, at which point it shows the correct final state.
How to solve this issue? Alternative to pausing algorithm at certain point?
First off, don't make the user wait for work that is done before they even think about when it will be finished. Its pointless. Please, just say no.
Second, you're "sleeping" the UI thread. That's why the UI thread is "locking up." The UI thread cannot be blocked; if it is, the UI thread cannot update controls on your forms and respond to system messages. Responding to system messages is an important task of the UI thread; failing to do so makes your application appear locked up to the System. Not a good thing.
If you want to accomplish this (please don't) just create a Timer when you start doing work that, when it Ticks, indicates its time to stop pretending to do work.
Again, please don't do this.
I'd guess everything is running out of a single thread. The user probably invokes this algorithm by clicking on a button, or some such. This is handled by your main thread's message queue. Until this event handler returns, your app's GUI cannot update. It needs the message queue to be pumped on regular basis in order to stay responsive.
Sleeping is almost never a good idea, and definitely not a good idea in the GUI thread. I'm not going to recommend that you continue to use sleep and make your GUI responsive by calling Application.DoEvents.
Instead, you should run this algorithm in a background thread and when it completes it should signal so to the main thread.
You are about to commit some fairly common user interface bloopers:
Don't spam the user with minutiae, she's only interested in the result
Don't force the user to work as fast as you demand
Don't forbid the user to interact with your program when you are busy.
Instead:
Display results in a gadget like a ListBox to allow the user to review results at her pace
Keep a user interface interactive by using threads
Slow down time for your own benefit with a debugger
This depends on a lot of things, so its hard to give a concrete answer from what you've said. Still, here are some matters that might be relevant:
Are you doing this on a UI thread (e.g. the thread the form-button or UI event that triggered the work started on)? If so, it may be better to create a new thread to perform the work.
Why do you sleep at all? If the state related to the ongoing work is available to all relevant threads, can the observer not just observe this without the working thread sleeping? Perhaps the working thread could write an indicator of the current progress to a volatile or locked variable (it must be locked if it's larger than pointer size - e.g. int or an object - but not otherwise. If not locked, then being volatile will prevent cache inconsistency between CPUs, though this may not be a big deal). In this case you could have a forms timer (there are different timers in .Net with different purposes) check the status of that variable and update the UI to reflect the work being done, without the working thread needing to do anything. At most it may be beneficial to Yield() in the working thread on occasion, but its not likely that even this will be needed.

Pattern for periodically updating screen data

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.

Multithreading on Windows Forms

I want to paralelize a 3D voxel editor built on top of Windows Forms, it uses a raycaster to render so dividing the screen and getting each thread on a pool to render a part of it should be trivial.
The problem arises in that Windows Forms' thread must run as STA - I can get other threads to start and do the work but blocking the main thread while waiting for them to finish causes strange random deadlocks as expected.
Keeping the main thread unblocked would also be a problem - if, for example, the user uses a floodfill tool the input would be processed during the rendering process which would cause "in-between" images (an object partially colored, for example). Copying the entire image before every frame isn't doable either because the volumes are big enough to offset any performance gain if it has to be copied every frame.
I want to know if there is any workaround to get the amin thread to appear blocked to the user in a way that it will not be actually blocked but will delay the processing of input till the next frame.
If it isn't possible, is there a better design for dealing with this?
EDIT: Reading the anwsers I think I wasn't clear that the raycaster runs in real time, so showing progress dialogs won't work at all. Unfortunately the FPS is low enough (5-40 depending on various factors) for the input between frames to produce unwanted results.
I have already tried to implement it blocking the UI thread and using some threads of a ThreadPool to process and it works fine except for this problem with STA.
This is a common problem. With windows forms you can have only one UI thread. Don't run your algorithm on the UI thread because then the UI will appear frozen.
I recommend running your algorithm and waiting for it to finish before updating the UI. A class called BackgroundWorker comes pre-built to do just this very thing.
Edit:
Another fact about the UI thread is that it handles all of the mouse and keyboard events, along with system messages that are sent to the window. (Winforms is really just Win32 surrounded by a nice API.) You cannot have a stable application if the UI thread is saturated.
On the other hand, if you start several other threads and try to draw directly on the screen with them, you may have two problems:
You're not supposed to draw on the UI with any thread but the UI thread. Windows controls are not thread safe.
If you have a lot of threads, context switching between them may kill your performance.
Note that you (and I) shouldn't claim a performance problem until it has been measured. You could try drawing a frame in memory and swapping it in at an appropriate time. Its called double-buffering and is very common in Win32 drawing code to avoid screen flicker.
I honestly don't know if this is feasible with your target frame rate, or if you should consider a more graphics-centered library like OpenGL.
Am I missing something or can you just set your render control (and any other controls that generate input events) to disabled while you're rendering a frame? That will prevent unwanted inputs.
If you still want to accept events while you're rendering but don't want to apply them until the next frame, you should leave your controls enabled and post the detail of the event to an input queue. That queue should then be processed at the start of every frame.
This has the affect that the user can still click buttons and interact with the UI (the GUI thread does not block) and those events are not visible to the renderer until the start of the next frame. At 5 FPS, the user should see their events are processed within 400ms worst case (2 frames), which isn't quite fast enough, but better than threading deadlocks.
Perhaps something like this:
Public InputQueue<InputEvent> = new Queue<InputEvent>();
// An input event handler.
private void btnDoSomething_Click(object sender, EventArgs e)
{
lock(InputQueue)
{
InputQueue.Enqueue(new DoSomethingInputEvent());
}
}
// Your render method (executing in a background thread).
private void RenderNextFrame()
{
Queue<InputEvent> inputEvents = new Queue<InputEvent>();
lock(InputQueue)
{
inputEvents.Enqueue(InputQueue.Dequeue());
}
// Process your input events from the local inputEvents queue.
....
// Now do your render based on those events.
....
}
Oh, and do your rendering on a background thread. Your UI thread is precious, it should only do the most trivial work. Matt Brundell's suggestion of BackgroundWorker has lots of merit. If it doesn't do what you want, the ThreadPool is also useful (and simpler). More powerful (and complex) alternatives are the CCR or the Task Parallel Library.
Show a modal "Please Wait" dialog using ShowDialog, then close it once your rendering is finished.
This will prevent the user from interacting with the form while still allowing you to Invoke to the UI thread (which is presumably your problem).
If you don't want all the features offered by the BackgroundWorker you can simply use the ThreadPool.QueueUserWorkItem to add something to the thread pool and use a background thread. It would be easy to show some kind of progress while the background thread was performing it's operations as you can provide a delegate callback to notify you whenever a particular background thread is done. Take a look at ThreadPool.QueueUserWorkItem Method (WaitCallback, Object) to see what I'm referring you to. If you need something more complex you could always use the APM async method to perform your operations as well.
Either way I hope this helps.
EDIT:
Notify user somehow that changes are being made to the UI.
On a(many) background threads using the ThreadPool perform the ops you need to perform to the UI.
For each operation keep a reference to the state for the operation so that you know when it completed in the WaitCallback. Maybe put them in some type of hash / collection to keep ref to them.
Whenever an operation completes remove it from the collection that contains a ref to the ops that were performed.
Once all operations have completed (hash / collection) has no more references in it render the UI with the changes applied. Or possibly incrementally update the UI
I'm thinking that if you are making so many updates to the UI while you are performing your operations that is what is causing your problems. That's also why I recommended the use of SuspendLayout, PerformLayout as you may have been performing so many updates to the UI the main thread was getting overwhelmed.
I am no expert on threading though, just trying to think it through myself. Hope this helps.
Copying the entire image before every frame isn't doable either because the volumes are big enough to offset any performance gain if it has to be copied every frame.
Then don't copy the off-screen buffer on every frame.

Categories