Why does the ProgressBar update in theoretically blocked UI thread?
In simple app I have a ProgressBar and a Label. I run a time-consuming method in UI thread which tries to update the ProgressBar and the label. This is not supposed to work, because of blocked UI thread. But the ProgressBar is updating!
Until I do anything on the form and it freezes, the ProgressBar updates (the label does not).
Why is that?
Example code (put a Button, a ProgressBar and a Label on form):
private void button1_Click(object sender, EventArgs e)
{
while (true)
{
progressBar1.Value += 1;
label1.Text += "1";
Thread.Sleep(100);
}
}
ProgressBar is updating, Label is not. My question is not how to make label update aswell, but why ProgressBar is updating. I DO know about Threads, DoEvents, async/await and that is not the answer.
I think it's hard to answer this completely without disassembling a bit of Windows, which is too much work for me right now.
But basically, when you set .Value on an WinForms ProgressBar control, it does little more than call SendMessage with message 1026 (PBM_SETPOS), which tells the Windows progress bar to set its position.
I would conclude that the Windows progress bar redraws itself synchronously in response to PBM_SETPOS as well as in response to WM_PAINT. Or perhaps it's running a timer on another thread in order to do the fancy glare animation, and that's able to redraw the control without waiting for a paint message.
Either way, it's just Windows internals you're seeing - and drawing stuff outside WM_PAINT handlers is not that an unusual technique, even though it's not the textbook way of doing things.
Actually, looking at the docs for PBM_SETPOS ( http://msdn.microsoft.com/en-us/library/bb760844(v=vs.85).aspx ) it's documented as causing a redraw - I guess this is done deliberately to help the lazy/inexperienced to get blocking progress bar updates to work without all usual hassle of doing it properly.
There are different approaches to answering your question. Let me explain. If you are running a lengthy task where the user has to wait to proceed, it actually doesn't matter whether you are running on the UI thread or not. Either way, the user has to wait for the task to complete to proceed, so they cannot use the application anyways.
However, in operations where you may want the user to interact with different parts of the application while the task is running, you create a worker thread to perform the said task. You need understand that the main UI thread is for, well, processing the UI. Painting a progress bar is part of the UI. The designed architecture of WinForms/.NET is that you create a background thread by means of the BackgroundWorker class, or wireup raw threads on your own. Its by design.
This all, however, will change drasitcally with C# 5.0 with the async and await keywords, as well as Task objects. You can search up TechDays 11 on channel9, or visit my Facebook (Posted about it a few posts down).
You can, to help remedy your situation if you feel inclined to keep your operation on the UI thread call Application.DoEvents() in your task to keep the Windows Messages flowing, or you can do it the right way and actually implement threading properly. Its very easy to wireup using the Thread class, a delegate, and invoking, and even easier to use a BackgroundWorker which was pretty much architected with the sole purpose of performing a task on another thread and reporting a 0/100% progressional value.
Related
I'm building a WPF application. I'm doing some async communication with the server side, and I use event aggregation with Prism on the client. Both these things results in new threads to be spawned which are not the UI thread. If I attempt to do "WPF operations" on these callback and event handler threads the world will fall apart, which it now has started doing.
First I met problems trying to create some WPF objects in the callback from server. I was told that the thread needed to run in STA mode. Now I'm trying to update some UI data in a Prism event handler, and I'm told that:
The caller cannot access this thread because a different thread owns it.
So; what's the key to getting things right in WPF? I've read up on the WPF Dispatcher in this MSDN post. I'm starting to get it, but I'm no wizard yet.
Is the key to always use Dispatcher.Invoke when I need to run something which I'm not sure will be called on the UI thread?
Does it matter if it actually was called on the UI thread, and I do Dispatcher.Invoke anyway?
Dispatcher.Invoke = synchronously. Dispathcher.BeginInvoke = async?
Will Dispatcher.Invoke request the UI thread, and then stop to wait for it? Is it bad practice and risk of less responsive programs?
How do I get the dispatcher anyway? Will Dispatcher.CurrentDispatcher always give me the dispatcher representing the UI thread?
Will there exist more than one Dispatcher, or is "Dispatcher" basically the same as the UI thread for the application?
And what's the deal with the BackgroundWorker? When do I use this instead? I assume this is always async?
Will everything that runs on the UI thread (by being Invoked) be run in STA apartment mode? I.e. if I have something that requires to be run in STA mode - will Dispatcher.Invoke be sufficient?
Anyone wanna clearify things for me? Any related recommendations, etc? Thanks!
Going over each of your questions, one by one:
Not quite; you should only invoke onto the UI thread when necessary. See #2.
Yes, it does matter. You should not just automatically Invoke everything. The key is to only invoke onto the UI thread if necessary. To do this, you can use the Dispatcher.CheckAccess method.
That is correct.
Also correct, and yes, you do run the risk of less responsive programs. Most of the time, you are not going to be looking at a severe performance hit (we're talking about milliseconds for a context switch), but you should only Invoke if necessary. That being said, at some points it is unavoidable, so no, I would not say it is bad practice at all. It is just one solution to a problem that you will encounter every now and then.
In every case I have seen, I have made due with Dispatcher.CurrentDispatcher. For complex scenarios, this may not be sufficient, but I (personally) have not seen them.
Not entirely correct, but this line of thinking will not do any harm. Let me put it this way: the Dispatcher can be used to gain access to the UI thread for the application. But it is not in and of itself the UI thread.
BackgroundWorker is generally used when you have a time-consuming operation and want to maintain a responsive UI while running that operation in the background. Normally you do not use BackgroundWorker instead of Invoke, rather, you use BackgroundWorker in conjunction with Invoke. That is, if you need to update some UI object in your BackgroundWorker, you can Invoke onto the UI thread, perform the update, and then return to the original operation.
Yes. The UI thread of a WPF application, by definition, must be running in a single-threaded apartment.
There's a lot to be said about BackgroundWorker, I'm sure many questions are already devoted to it, so I won't go into too much depth. If you're curious, check out the MSDN page for BackgroundWorker class.
When I run the program in one fast computer, the ProgressBar and a Label(that write the progress too) gets perfectly updated. When I run it on a weak computer (like PIV or old c2d) the ProgressBar and the form stay freezed (but the program run until it finishes).
How can I resolve that? With background worker?
If you're using a progress bar, I'm guessing whatever the task is is definitely long enough to warrant a background/worker thread. There are lots of options (BackgroundWorker, spinning up your own thread, etc). BackgroundWorker is probably the easiest.
Yes, you should put your processing into a background thread. Using a background worker is a good idea, because you can simply update the controls from its ProgressChanged event.
There are some methods that allow the UI to be refereshed in long-running tasks.
1- run the task in another tread/in an anychronous method call and then using this.Invoke to change the progressbar.
2- Force the UI to refresh at some points in the task by calling Application.DoEvents() in winforms for instance.
Sometimes I saw that when I call a method from my form to do something that my UI freezes. How to solve this problem? If I call that method in separate thread then problem will be solved?
If I call method in separate thread like the code below
new System.Threading.Thread(delegate()
{
HeavyMethod();
}).Start();
does this solve my problem or is there any better solution?
Call the method on a Background Worker would be the best solution.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Doing that you can control when things get updated (using the Report Progress Feature) and allow you to cancel the work.
Also, make sure that whatever resources you manipulate in the backgroundWorker1.RunWorkerAsync(); are properly shared. You can get into what is called "Race Conditions" which causes your output to be non-determanistic (e.g. you won't get the same results every time you run the method)
For a good walk through on Multithreading and shared resources, see this link:
http://www.c-sharpcorner.com/uploadfile/mgold/multithreadingintro10062005000439am/multithreadingintro.aspx?articleid=920ecafc-e83b-4a9c-a64d-0b39ad885705
If you are calling your method in response to an event, then by default the method will be running on the GUI thread (the thread that the runtime uses to handle all user events). If that method is huge and/or heavy, then it will "freeze" the UI as you describe.
Making it run on a separate thread is a viable solution for many of these cases.
There are cases, however, when you'll actually want the UI to "block" (for example, if you are updating a lot of controls, you don't want the user to mess with them in the meanwhile). For such cases, the sanest approach is to pop up a modal "wait" dialog.
Since it is C# 2.0, I suppose it is WinForms. Don't hold up the UI thread with CPU-bound code.
You can spawn a new thread to run your CPU-bound code, but you have to be careful not to access WinForms controls, especially not to update control properties. Many WinForms controls can only be accessed/updated from the UI thread. Check the InvokeRequired field to see if you need to marshal (i.e. use Invoke) the call from another thread back to the UI thread.
Also consider using the ThreadPool instead of creating a new thread.
That is correct, If you move the heavy processing off of the UI Thread then it should free up the UI to redraw. For what you want to do your implementation should work just fine. Although ThreadPooling or BackgroundWorker would be the suggested implementations (http://msdn.microsoft.com/en-us/library/system.threading.threadpool(v=VS.80).aspx), (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx).
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.
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.