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();
}