In my program I let the user to specify the processing parameters in the main dialog and after the user pushes the "Run" button all the controls on the dialog are disabled (and invisible) and the progress bar is shown which tracks the calculation flow. In the program I want all the controls to stay invisible until the calculations are completed at which point the progress bar should disappear and everything else shows up again.
What is often happening to me is that if the calculation is continuing for a "long" time (a minute or so) the progress bar gets frozen (i.e. does not show progress in the calculations). At the same time, I can move the dialog itself and see that there is a copy of this main dialog under it on which the progress bar is still updating as it should, however the copy of this window can no longer be moved (although the original window can). After the calculations are completed "the copy" of the dialog disappear and the original is enabled and is fully functional as it should be. What I also see, that in the taskbar the tab corresponding to the "new copy" of the dialog appears after I try moving the original dialog, this tab disappears after the calculations are finished.
This situation is illustrated in the attached image - TOP: the "copy" of the dialog that appears after the "original" dialog has been moved - note that the progress bar in the "copy" is constantly updating; MIDDLE: the "original" dialog with frozen progress bar; BOTTOM: taskbar with tabs for both original dialog and its copy.
Can anybody explain what is going on? How can I keep the progress bar in the original dialog going during the whole calculation cycle and skip the creation of the copy?
It is not a 'copy', it is likely due to the fact that your processing is taking place in the UI thread. Let me introduce you to the Windows message pump. Your window is simply not updating predictably because you are clogging the UI thread with your calculations. You should launch that in a separate thread and update the UI periodically through the use of a delegate.
If you liked my post go ahead and give me an upvote so that my epee.... ahem, reputation will grow.
Thank you for your reply. Unfortunately, I can not completely understand what you are talking about (excuse my layman ignorance). In my application the calculation program actually calls the progress bar update program every time it wants it to update (i.e. after each completed step).
Can you provide more guidance or references on this problem? I read the wikipedia article but it is TOO general.
My code is a little bit clamsy, but in the nutshell, here is what I do:
Code:
namespace Calculations
{
public delegate void LabelUpdate(int i);
public LabelUpdate UpdateFunction = null;
public int CurrentStep = 0;
public int ProcessingSteps = 0;
public void CalculationProcess(UpdateFunction Func, int PSteps, ...)
{
// Let the drawing function know how many total steps are expected
// in order to correctly draw the image and label in the image
// of my progressBar
InitializeLabelUpdate(PSteps);
for(int i=0; i<PSteps; i++)
{
... // Do the calculations for the step
if(Func!=null) Func(1);
}
}
public void InitializeLabelUpdate(int TotalSteps)
{
CurrentStep = 0;
ProcessingSteps = TotalSteps;
pictureBox1.Show();
DrawPictureBox(0);
}
// Example of the function that can be sent to "CalculationProcess"
public void PBar(int Delta)
{
CurrentStep += Delta;
DrawPictureBox(CurrentStep);
}
}
My progress bar is implemented as a pictureBox in which I can place a certain text and draw some bitmap in which certain part of it will be green based on the value of CurrentStep and ProcessingSteps. If CurrentStep changes - I change the bitmap that I place in it.
That code cannot be the whole picture, it wouldn't even compile (you cannot define methods and variables directly in a namespace in C#). How about uploading the entire thing for us?
If you liked my post go ahead and give me an upvote so that my epee.... ahem, reputation will grow.
As I said, it is a little bit involved - putting the whole code that compiles would require a removal of a lot of confidential information. Again, in the nutshell, the code basically redraws the bitmap and places it in the pictureBox at each new processing step. On some occasions it works as expected (as I expect and want it) - the problems occur when the process becomes lengthy in time (more than a minute).
Could you suggest some reading material for me or posts that deal with a similar problem?
Ok then. Basically, the way Windows Forms works is a message queue model. Messages are sent to the UI by the operating system and queued up to be processed by a function called a window procedure (WndPrc). If you are inside of a tight loop that is running on the UI thread these messages cannot be processed, i.e., the queue fills up and numerous repaint messages are ignored. Take a look at the BackgroundWorker class which allows you to easily assign tasks to another thread.
That said, your description does not sound entirely typical of this situation, but it is the best idea I have. We can be sure at least that, if you are running this loop on the main UI thread, it is clogging up your UI.
If you liked my post go ahead and give me an upvote so that my epee.... ahem, reputation will grow.
The problem is that you are performing cpu intensive work inside your main ui thread.
Even though you are calling to update the progress bar in each loop iteration, since you are immediately returning back to the calculations the UI thread doesn't get a change to process messages.
The typical way to handle this is to put the calculations into a separate thread as BigEd mentioned.
There are some details with regard to accessing UI controls from a secondary thread, see:
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.