I want to have my own progress bar in .net compact framework, instead of default wait cursor.
I have tried with a form, having only a progress bar, and showing and hiding the form when I want to show some background activity running, but that does not update the progress bar.
I have found out that it needs to be on different thread. I am quite weak at threads, I cant get it working.
Please help me out.
Thanks in advance.
A cheap way of doing this would be to use Application.DoEvents(); within your "background work"... This would allow the screen to update whilst your application is busy.
I do not recommend doing this though.
I suggest you learn how to start and use BackgroundWorkers. They should provide the functionality you are looking for. Note you will not be able to alter the progress bar directly from the new thread, so will have to use an event or delegate.
Related
I have a small winform application and i put a progress bar on first running form. This progress bar completes in 10 seconds and after progress bar completes the next activity starts like database call.
I want when this progress bar runs for 10 seconds, during this time database call should do its work instead of calling after the progress bar completes.
Can anyone explain or have sample code to explain this technique ???
Thanks in advance.
Your issue probably arises from the fact that you are running the heavy duty work on the User Interface Thread, so basically you are holding that thread from doing anything.
To solve this issue you need to run on a separate Thread and Control.Invoke the progress bar control when it needs update.
Check out Threading and the UI on VS Magazine.
You need to use a background worker!
Do your heavy operation in the background worker thread and on the UI thread keep the progress bar running.
You should find plenty of examples about the usage of a background worker, some here:
http://www.dotnetperls.com/backgroundworker
https://stackoverflow.com/a/15153258/2243584
There are many good multi-threading tutorials out there that explain in ample detail this question. Googling "winforms thread sync" this is the first one that comes up. Pretty good.
I have a Windows app that basically calls other classes and within thise stored procedures and ultimately creates a csv file of a lot of info. I need a progress bar that just runs until its done so the user can see something is happening. I have scoured the internet and cant seem to get this to work. I just want the bar to start running on a button click. Why does this seem so difficult? The closest I got is just starting the bar in marquee but it wont "start" until after the object has been filled which does me no good, I need it to start while the object is being filled. This is being done in C#. Any ideas?
You need to run the long running task in a separate thread so that the UI can update while the task runs.
See Windows Forms ProgressBar: Easiest way to start/stop marquee? for an example of setting this up.
I have written an application which does lots of calculation on huge floating point numbers that makes the UI not responsive at all most of the time.
I am thinking of adding a status bar to this application and show some info about cpu load, used memory and a progress bar. Consider adding labels and progress bar to the statusbar as childs, how can I run this status bar on a separate thread which can be reliable to be responsive as much as possible?
I can already use progress bars and system diagnosting stuff normally. What I am looking for is your ideas and tips, possibly with some codes!
Update
I want the status bar shows real time cpu and memory details. How to workaround this?
You've got this the wrong way round. You should run all the UI in the same thread, and run the long calculation in a background worker. Trying to run UI in different threads within the same app just leads to pain.
Best thing is to just do a google search on BackgroundWorker. Here is one particular result on how to use it.
http://midnightprogrammer.net/post/Using-Background-Worker-in-C.aspx
My program consists of a large graphing UI control that I need to spend about 15 seconds re-loading every once in a while. Because the updating code works primarily with the UI control (maybe 90% of it actually sets properties on the control), it would make sense to me to actually let the UI thread handle that. I really don't want the control to visually re-paint while it is loading in a separate thread from the UI.
I also want a progress bar to update as well that lives in the status bar of the same application window. Is there a way to break the rule in this case and re-paint only the progress bar, or should I just open a new application window for the progress bar to live in?
What would you do in this particular case?
If you can break your primary task (ie. updating the graph) in many steps, you can perform each step as a separate dispatcher message. This will allow other messages to be processed, including giving you the ability to update progress information.
The basic pattern is:
Invoke your primary task, passing in zero for the step.
Perform the step.
If there are more steps, queue another message, passing in step + 1.
You can then add in progress updates at the appropriate points in your code.
PS. Not saying this is your best option - hard to tell without knowing all the details. But this is an option.
It is not really true that there is only one UI thread in an application, it is just that most windows applications only ever create UI objects in one thread so this thread becomes "the" UI thread in the application. It is easy to understand why - this makes the code simpler to understand, and protects us from implicit thread binding issues between controls.
This suggests a possible idea, should it prove impossible to improve the speed of updating the control (which is what I would suggest to do first). Create the UI control on a separate thread. You need to make sure that the thread is suitable for UI, that is to say the threading model is STA, and that it will pump messages and not die before the control is destroyed. I don't know if you need to create the parent window in the UI thread as well, or just the control but it may be worth experimenting here.
Find a graphing UI control that is more efficient. Unless the UI thread yields to the message loop any other updates won't happen (and it will slow down your graph control's updates).
I would suggest using a progressbar in a new window (without the form headers). Make it paint the progress bar by reading the shared properties of a graph control. this way you can avoid the thread blocking (sluggish loading).. And it gives you good visual experience (progressive painting on both the controls).
I'm building a UI for a program, and I can't figure out why my progress bar won't become visible after the convert button is clicked.
private void convertButton_Click(object sender, EventArgs e)
{
toolStripProgressBar.Visible = true;
...
toolStripProgressBar.Visible = false;
}
I ran into a similar problem with tkinter in Python, and I had to call a function to update the idle tasks. Is there a way to do this with windows forms without using threads?
Edit: On a side note, this is a progress bar in a toolStrip that also contains a label that gets updated with status bar text. Is there any way to get the label on the left side and the progress bar on the other instead of right next to each other on the left?
Well, there is a way to do this without using threads (Application.DoEvents) but I strongly recommend against you using it. Re-entrancy is nasty, and you really don't want the UI thread tied up at all.
Use BackgroundWorker instead - it's easy, and it's pretty much designed for progress bars. It takes the hassle out of using a separate thread and reporting progress back to the UI thread. No need for Control.Invoke etc - it takes care of that for you.
There are lots of tutorials for BackgroundWorker - it shouldn't take you too long to get going with it.
Per the question you asked for the way to do this WITHOUT threads, that is to do it with Application.DoEvents();. (Just add that call right after setting the progress bar as visible.)
Now I do agree with Jon Skeet though that BackgroundWorker is a better way of doing this, but it does use a separate thread.
You need to execute your process in a thread separate from the UI thread, and then have it periodically report back to the UI thread with it's progress. If your convert operation is working inside the UI thread, it will simply go unresponsive until the operation is complete.
The progress bar can only become visible when it is allowed to paint which occurs during the processing of messages. Message processing cannot normally happen while you are in the middle of an event handler. If you want the progress bar to show up you will have to set the visiblitity to true, start a background thread to complete the work and return from the handler.
I'm guessing the problem is that the "..." in your code is a long-running process. UI updates are not instantaneous, but must run through the message queue in windows and then be painted to the screen. The queue is pumped and painting takes place in the same thread as your events.
As a result, any long-running tasks need to be moved to a different thread. More than that, your line line of code needs to called after that thread terminates. Otherwise you set the progress bar and then immediately turn it off again.
One way to do that is with a BackgroundWorker control.
Here go two links trying to explain you how things work:
(1) (2)
Now, I will try to explain it as shortly as I can. Most of what happens inside a windows forms application happens in a single thread, usually the same thread Main() runs in. If you open Program.cs, you will see that Main() has a line that looks like the following:
Application.Run(new Form1());
If you debug the application at any moment and examine the call stack, you will see it will trace back to that Run method. This means that a Windows Forms application is in fact a continuous run of the Run method. So, what is Run doing? Run is eating a message queue through which Windows sends messages to it. Run then dispatches those messages to the correct controls, which themselves do things like add text which corresponds to the key being pressed, redraw themselves, etc. Notice that all this happens during and endless loop running alongside a single thread, so weather you are typing or simply moving the window around, loads of those messages are being passed onto the application, which in turn is processing them and reacting accordingly, all in that single thread. Controls can also send messages to themselves through the queue and even you can place messages in the pump via Control.BeginInvoke. One of the things those controls do is to raise events according to what happens. So, if you click a button, the code you've written to handle that click will ultimately and indirectly be run by the Application.Run method.
Now, what is happening with your code is that even though you are changing the visible status of your progress bar to visible and then updating its Value, you are then changing its visibility to false, all in the same method. This means that only after you leave the method, will Application.Run() be able to continue iterating and consuming the message queue, effectively asking the progress bar to update its display. When that happens, you've already left the progress bar's visibility to false, the last thing you did before exiting the method. DoEvents() is a quick and dirty workaround to your problem as it reads the messages in the queue and processes them. I don't really feel comfortable using it as it can bring reentrancy problems.
Using threads is a good solution, but I would recommend using a ThreadPool thread instead of a custom thread in this kind of situation, as I tend to use custom threads only in cases where I have a limited number of long lived threads and I need to control their life cycles. The easiest and most practical way to use threads is to use the BackgroundWorker component, even though I would recommend going through the pains of understanding how to do Windows Forms multithreading with delegates if you want to really understand what is going on.
My solution is to call refresh on the status strip.
I believe this causes the UI thread to repaint the status strip.
toolStripStatusBar1.PerformStep();
statusStrip1.Refresh();
This is for .NET 4.0. Even though this question is old it was the first I found on googling this issue.