Winform利用进度条和文件复制
Winform utilizing progress bar and file copying
我有一个带有发布按钮、取消按钮、标签和进度条的表单。当我单击该按钮时,复制到不同目录所需的所有文件都将被复制。这部分工作正常。我现在使用进度条让用户知道在任何给定时间正在发布什么文件。这样,如果出现问题或文件非常大,用户就知道是什么文件导致了问题(通过标签)。这些文件通过字符串列表填充。最初,我只是使用 Thread.Sleep 使过程比复制文件的瞬间更长。但是,仅使用它会阻止与 UI 的交互(例如,如果用户想要取消)。所以我正在使用 BackgroundWorker 来解决我的问题。
点击 "publish"
时我期望发生什么
标签告诉我 "Starting publication..."。每个文件后,进度条值增加,标签表示正在发布的文件,当复制结束时,标签显示"Publish Complete",进度条值最大。
不会发生的事情
文件的标签没有更新。它只是说 "Starting publication" 然后 "Publish Complete"。
问题
如何正确 "ReportProgress" 以便在每个文件被复制后更新我的标签?
代码
private void btnPublish_Click(object sender, EventArgs e)
{
try
{
ProgressBar();
}
catch (Exception ex)
{
Data.Common.ErrorHandling.DisplayError(ex);
}
}
private void ProgressBar()
{
lblPublish.Text = "Starting publication...";
//DoWork
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy)
{
backgroundWorker1.CancelAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
List<string> allAcros = NumOfTotalAcros();
foreach (var acro in allAcros)
{
backgroundWorker1.ReportProgress(allAcros.IndexOf(acro));
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
backgroundWorker1.ReportProgress(0);
return;
}
Thread.Sleep(500);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
List<string> acros = new List<string>();
cdsPublishBar.Value = e.ProgressPercentage;
for (int i = 0; i < acros.Count; i++)
{
lblPublish.Text = "Processing " + acros[i].ToString() + "...";
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
lblPublish.Text = "Processing cancelled";
}
else if (e.Error != null)
{
lblPublish.Text = e.Error.Message;
}
else
{
cdsPublishBar.Value = 100;
lblPublish.Text = "Publish Complete";
}
}
您正在创建一个新的 empty 集合,它与 DoWork
事件中的集合无关,然后对其进行迭代......这永远不会打印任何东西。
// empty list
List<string> acros = new List<string>();
// no elements to iterate over
for (int i = 0; i < acros.Count; i++)
{
lblPublish.Text = "Processing " + acros[i].ToString() + "...";
}
相反,通过 ReportProgress
的第二个参数传递您需要的值:
backgroundWorker1.ReportProgress(0, acro);
然后在 ProgressChanged
方法中使用它:
cdsPublishBar.Value = e.ProgressPercentage;
lblPublish.Text = string.Format("Processing {0}...", e.UserState);
我有一个带有发布按钮、取消按钮、标签和进度条的表单。当我单击该按钮时,复制到不同目录所需的所有文件都将被复制。这部分工作正常。我现在使用进度条让用户知道在任何给定时间正在发布什么文件。这样,如果出现问题或文件非常大,用户就知道是什么文件导致了问题(通过标签)。这些文件通过字符串列表填充。最初,我只是使用 Thread.Sleep 使过程比复制文件的瞬间更长。但是,仅使用它会阻止与 UI 的交互(例如,如果用户想要取消)。所以我正在使用 BackgroundWorker 来解决我的问题。
点击 "publish"
时我期望发生什么标签告诉我 "Starting publication..."。每个文件后,进度条值增加,标签表示正在发布的文件,当复制结束时,标签显示"Publish Complete",进度条值最大。
不会发生的事情
文件的标签没有更新。它只是说 "Starting publication" 然后 "Publish Complete"。
问题
如何正确 "ReportProgress" 以便在每个文件被复制后更新我的标签?
代码
private void btnPublish_Click(object sender, EventArgs e)
{
try
{
ProgressBar();
}
catch (Exception ex)
{
Data.Common.ErrorHandling.DisplayError(ex);
}
}
private void ProgressBar()
{
lblPublish.Text = "Starting publication...";
//DoWork
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy)
{
backgroundWorker1.CancelAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
List<string> allAcros = NumOfTotalAcros();
foreach (var acro in allAcros)
{
backgroundWorker1.ReportProgress(allAcros.IndexOf(acro));
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
backgroundWorker1.ReportProgress(0);
return;
}
Thread.Sleep(500);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
List<string> acros = new List<string>();
cdsPublishBar.Value = e.ProgressPercentage;
for (int i = 0; i < acros.Count; i++)
{
lblPublish.Text = "Processing " + acros[i].ToString() + "...";
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
lblPublish.Text = "Processing cancelled";
}
else if (e.Error != null)
{
lblPublish.Text = e.Error.Message;
}
else
{
cdsPublishBar.Value = 100;
lblPublish.Text = "Publish Complete";
}
}
您正在创建一个新的 empty 集合,它与 DoWork
事件中的集合无关,然后对其进行迭代......这永远不会打印任何东西。
// empty list
List<string> acros = new List<string>();
// no elements to iterate over
for (int i = 0; i < acros.Count; i++)
{
lblPublish.Text = "Processing " + acros[i].ToString() + "...";
}
相反,通过 ReportProgress
的第二个参数传递您需要的值:
backgroundWorker1.ReportProgress(0, acro);
然后在 ProgressChanged
方法中使用它:
cdsPublishBar.Value = e.ProgressPercentage;
lblPublish.Text = string.Format("Processing {0}...", e.UserState);