Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / WinForm General / August 2007

Tip: Looking for answers? Try searching our database.

A *generic* progress bar dialog with BackgroundWorker?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Jugalator - 28 Aug 2007 16:00 GMT
Hi!

I'm having some trouble with BackgroundWorker objects and making some
"heavy" work that is *not* supposed to be in the progress bar dialog itself.
I basically want to do something like this:

ProgressForm form = new ProgressForm();
form.Show();
// ... Do heavy work here ...
form.UpdateProgress(label, progressValue);
// ... More heavy work ...
// Done!
form.Close();

And by doing this, have ProgressForm coded so it dosen't lock up the UI.
Would this be possible? My problem is that doing the work in the
ProgressForm's DoWork event handler used by the BackgroundWorker is not an
option because that would make ProgressForm work-specific, which I'd really
dislike to see. I want a reusable progress dialog, not make the dialog
specific depending on the heavy work I wish to do.

So far most examples I've seen on the web seem to be about work-specific
progress dialogs where the "heavy work" is in the DoWork function itself. :(

So I've played around with constructing the ProgressForm with an argument
being a delegate to the calling class' "heavy work" function, that will be
called back by the DoWork() handler. The "heavy work" function would have a
ProgressInfo object as return value, which would contain the progress value
and label to use after it returns from being called in DoWork().

That seemed like a bright idea until I saw that I then need the work in its
own function, which makes me need to supply it with its set of arguments
(like an array of objects to process), and the only option I can then see is
the make such arrays and everything related to the "heavy work" fields in the
calling class. :-/

Is there a "pretty" way out this by keeping things reasonably simple and not
hardwiring my heavy work loop into/inside the progress bar dialog class
itself?
Jugalator - 29 Aug 2007 09:46 GMT
OK, I'll reply to myself with the solution I have working now. The only
"imperfect" thing for what I'd like now is that I need to pull out the
variables from the function delegate that'll be called from the worker
function, because I want to generalize the worker function.

Here's my code if anyone's interested...

First, the generic ProgressForm:

(lblWork is a label telling what it's currently doing, like which file it's
working on in a series... I have placed a "worker" object of type
BackgroundWorker in design mode, set to WorkerReportsProgress = true and
WorkerSupportsCancellation = true)

----------------

using System.Windows.Forms;

namespace MyNamespace // set this to whatever you use
{
   public partial class ProgressForm : Form
   {
       // The callback function for the BackgroundWorker's DoWork()
       public delegate ProgressInfo HeavyWorkFunction();

       private readonly int max;
       private readonly HeavyWorkFunction workFn;

       public ProgressForm(string title, int max, HeavyWorkFunction workFn)
       {
           InitializeComponent();

           this.Text = title;
           this.max = max;
           this.workFn = workFn;

           worker.RunWorkerAsync();
       }

       private void worker_DoWork(object sender,
System.ComponentModel.DoWorkEventArgs e)
       {
           ProgressInfo pi;
           while ((pi = workFn()).progress < max)
               worker.ReportProgress(100 * pi.progress / max, pi.label);
       }

       private void worker_ProgressChanged(object sender,
System.ComponentModel.ProgressChangedEventArgs e)
       {
           progress.Value = e.ProgressPercentage;
           lblWork.Text = (string)e.UserState;
       }

       private void worker_RunWorkerCompleted(object sender,
System.ComponentModel.RunWorkerCompletedEventArgs e)
       {
           Close();
       }
   }

   public class ProgressInfo
   {
       public string label;
       public int progress;
   }
}

----------------

Then, a sample usage... For example, synchronizing a bunch of files with a
mobile device.

----------------

public void Synchronize()
{
           // At this point, the variable totalSize contains the total
number of bytes to transfer
           pi = new ProgressInfo();
           ProgressForm form = new ProgressForm("Synchronizing...",
               totalSize, SyncWorker);
           form.ShowDialog();
}

/* Field variables... This is the annoying part -- need more fields the more
complex and dependant the SyncWorker() function is on the rest of the class,
in order to keep ProgressForm a 100% "generic" class. */

private int currentSize, totalSize;
private int nextPos;
private List<FileInfo> files;
private ProgressInfo pi;

public ProgressInfo SyncWorker()
{
   FileInfo fileInfo = files[nextPos];

   // This takes some time...
   device.CopyFileToDevice(fileInfo.FullName,
  destDir + @"\" + fileInfo.Name);

   currentSize += (int)fileInfo.Length;

   pi.label = string.Format("Copying {0} (transferred {1} bytes) ...",
fileInfo.Name, currentSize);
   pi.progress += currentSize;

   nextPos++;

   return pi;
}
Jugalator - 29 Aug 2007 09:52 GMT
Oops, forgot the Cancel handler in the ProgressForm... But it's simple
enough. ;)

       private void btnCancel_Click(object sender, System.EventArgs e)
       {
           worker.CancelAsync();
       }

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.