 |
|
 |
I was having an occasional problem with an unhanded ObjectDisposedException in my program using BusyBar. after a lot of research i found an error in the order of the Dispose(bool disposing) function of the BusyBarBase class. The base was being disposed before stopping the thread allowing the occasional call to invalidate an disposed object.
The Fixed Code
protected override void Dispose(bool disposing)
{
_bDisposing = true;
bool bRet = _thread.Join( new TimeSpan(1,1,1,1) );
bRet = _thread.IsAlive;
base.Dispose(disposing);
}
|
|
|
|
 |
|
 |
OK, now when I put BusyBar in action I have the following problem. I put the busy bar (more specifically ColorFadeBusyBar)in a modeless form. I call form.Show() and then proceed with some lenghty operations. After each of the gets finished I update the text in the busy bar calling a function UpdateText(text).
The problem is that the busy par does not repaint properly after each step. So it looks like frozen. I added Application.DoEvents() after changing text in the UpdateText(). Then it succeeds to refresh its position. But if UpdateText() is not called regularly the busy indicator seems frozen which is a problem.
I tried to find a workaround by putting Application.DoEvents() in an appropriate place. So I tried it the WorkerThread() function of BusyBarBase, but this seemed to have no effect. Is such an approach a good one? I guess I can play more with that, but if anyone has a solution please let me know.
Ivan Mitev
|
|
|
|
 |
|
 |
Hmm, I am not getting any real progress till now. Though I tried a bunch of things that DO NOT work . Btw, the same painting problem can be observed with the standart System.Windows.Forms.ProgressBar. So let see what I tried that does not work:
Adding a timer component to the modeless form and calling this.Refresh() and Application.DoEvents() each X microseconds
Initializing a System.Timers.Timer in the main thread and doing the same thing each X microseconds (this is basically the same thing).
Adding Application.DoEvents() in various places in the WorkerThread() method which calls this.Invalidate()
I guess I have to be more creative or read more on message pumping and modeless forms
Ivan Mitev
|
|
|
|
 |
|
 |
OK, this thread is turning into a monologue, but I have to share the workaround, I found. It is rather simple.
Instead of opening the form, containing the BusyBar in a modeless mode with Form.Show(), I just started a new thread and put Form.ShowDialog() there. I mean:
_progressFormThread = new System.Threading.Thread(new System.Threading.ThreadStart(_progressForm.ShowModal)); _progressFormThread.IsBackground = true;
_progressFormThread.Start();
where ShowModal() is just ShowDialog() but with void return type.
And it is just working with no extra effort. Cool!
Well, some conclusions can be drawn from this fact, but I won't go in the analysis here...
Ivan Mitev
|
|
|
|
 |
|
 |
hi ivan
i was very busy the last few days. i didnt get a change to have a look into the sources.
i will do that in a few days.
thx for your work!
|
|
|
|
 |
|
 |
Very good job,
I encountered a little problem when trying to view the busy bar user controls in VS.NET IDE. The reason is that the base classes (as BusyBarBase) are marked as abstract and the VS.NET IDE prevents me to visualize them in design mode (and unfortunately their subclasses too). So I just removed the "abstract" modifier, thus sacrificing good design for ease of use.
I also have to mention that I like the interesting techinique you used in the demo code of switching from Tab to Form with #ifdef EDIT_MODE as a workaround of the designer problem. Very nifty!
Ivan Mitev
|
|
|
|
 |
|
 |
hi ivan
thx for your post.
if i am going to insert a busy bar into a form, i don't have any problem. could you explain the behaviour more detailed please?
about the EDIT_MODE stuff: it took a long to find this workaround.
for stuff like that, the VS.NET designer really sucks.
|
|
|
|
 |
|
 |
The problem was not with inserting busy bar in a form. It was when trying to view it as a user control. When you click on a user control it usually opens in design view. But I got some error from the IDE, so I could only look at code in Code view. Not that the Design mode is very useful in this case... but still I decided to fix this.
Ivan Mitev
|
|
|
|
 |
|
|
 |
|
 |
thx
|
|
|
|
 |
|
|
 |
|
 |
Great control!
One thing that would help to reduce the flickering it to set double buffering.
My addition to the base constructor:
public BusyBarBase()
{
this.ForeColor = DefaultForeColor;
this.BackColor = DefaultBackColor;
this.Size = new Size( 300, 25); //default size
CreateBackgroundBrush();
// Turn on double buffering to reduce flicker here
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
UpdateStyles();
_thread = new Thread( new System.Threading.ThreadStart( WorkerThread ) );
_thread.Start();
}
Matt
|
|
|
|
 |
|
 |
Totally unrelated to this particular project, but your double buffering tips just helped me out a whole bunch.
Thanks!
Chris
|
|
|
|
 |
|
 |
on flatscreens i really do not see big difference. but on CRT screens i see a small flickering.
|
|
|
|
 |
|
 |
Imagine you load something via HTTP. If you have a Content-Length header you know in advance how many bytes to expect. You can calculate a percentage and display it using a progressbar. But what, if you don't get this Header you want to indicate to the user that you are not yet finished? Here a busybar would be the right thing. So why not combine these two kinds of controls?
|
|
|
|
 |
|
 |
this would be the same as norm.net has posted here.
right?
|
|
|
|
 |
|
 |
Not exactly. I suggest to implement 2 different "modes":
1: ProgressBar mode.
The control looks and acts like a standard Progress bar with an upper and lower bound and a current value. This current value is than shown as a bar growing from left to right (resp. top to bottom). Text would be nice anyway.
2: BusyBar mode.
Basically what you have now.
|
|
|
|
 |
|
 |
now i see. but this is the no busy bar then. but i created something like this a long time ago. maybe i am going to post an article about this. how sounds this?
|
|
|
|
 |
|
 |
you may want to add a method to set text, which would display in the middle of the bar eg;
bar1.TextColor = Color.White;
bar1.Text = "Processed 10%";
just a thought?
|
|
|
|
 |
|
 |
nice idea but i do not see an "use case" for this.
when it would be useful?
your code:
bar1.TextColor = Color.White;
bar1.Text = "Processed 10%";
if you do not know the timespan of an operation to complete, the busybar can be used. but you do NOT know the how much of your operation has completed.
see what i mean?
|
|
|
|
 |
|
 |
Ok, cases when you want to a busy bar are loading file or processing data, the idea would be to show some text indicating the progress.
|
|
|
|
 |
|
 |
you convinced me. i will do it
|
|
|
|
 |
|
|
 |