问题
I'm creating option to backup data of my app with DotNetZip and to avoid freezing the app I've found that the best way for a this type of action best way is to use BackgroundWorker. So I came with something like this:
private void processButton_Click(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
BackupParams bp = new BackupParams();
bp.Source = inputTextBox.Text; // source dir
bp.Output = outputTextBox.Text; // output file
bp.Password = @"Pa$$w0rd";
worker.RunWorkerAsync(bp);
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show((string)e.Result, "Zip", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackupParams bp = (BackupParams)e.Argument;
string id = Guid.NewGuid().ToString();
comment += "Created at: " + DateTime.Now.ToString() + "\n";
comment += id;
ZipFile zf = new ZipFile();
zf.Comment = comment;
zf.CompressionMethod = CompressionMethod.BZip2;
zf.CompressionLevel = CompressionLevel.BestCompression;
zf.Encryption = EncryptionAlgorithm.WinZipAes256;
zf.Password = bp.Password;
zf.Name = bp.Output;
zf.AddDirectory(bp.Source);
zf.Save();
e.Result = bp.Output;
}
and this is BackupParams
public class BackupParams
{
public string Source { get; set; }
public string Output { get; set; }
public string Password { get; set; }
}
And right now I'm stuck cause I want to show the progress (percentage with names) of files added to the archive. What is the best way to do this? I know i can use those methods from ZipFile
zf.SaveProgress += zf_SaveProgress;
zf.AddProgress += zf_AddProgress;
but from those I don't have access progressbar or label that are on form...
回答1:
For sending a progress report out from a BackgroundWorker you use ReportProgress()
inside your DoWork
method.
void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker theWorker = (BackgroundWorker)sender;
theWorker.ReportProgress(0, "just starting");
BackupParams bp = (BackupParams)e.Argument;
...
This then fires off your worker_ProgressChanged
method, so you can take the report from there into your controls.
The trick is that you have to make another function to handle the progress change with your zip creation. You can't access your UI controls here because they are on a different thread. You should be able to create a lambda for this (and I don't know the exact parameters, please fix if I'm wrong)
zf.SaveProgress += (sender, eventArgs) =>
{
// Check if EvenType equals Saving_AfterWriteEntry or NullReferenceException will be thrown
if (eventArgs.EventType == ProgressEventType.Saving_AfterWriteEntry)
{
theWorker.ReportProgress(eventArgs.EntriesSaved, "Saving "+ eventArgs.CurrentEntry.FileName);
}
};
zf.AddProgress += (sender, eventArgs) =>
{
// Check if EventType equals Adding_afterAddEntry or NullReferenceException will be thrown
if (eventArgs.EventType == ZipProgressEventType.Adding_afterAddEntry)
{
theWorker.ReportProgress(eventArgs.EntriesAdded, "Adding "+ eventArgs.CurrentEntry.FileName);
}
};
来源:https://stackoverflow.com/questions/19416209/dotnetzip-in-backgroundworker-update-progressbar-and-label-on-a-form