我有自己的解决方案,可以在我的Windows窗体应用程序中导入月度销售数据。当用户单击import
按钮时,程序实际上正在运行,但看起来它没有响应。这个过程需要很长时间,大约需要5分钟。
因此,我想实现一个带有状态条标签的进度条,以显示为用户界面,让用户知道完成任务的程度。这也是我第一次在程序中使用进度条。所以,我阅读了一些教程,展示了如何使用它。有些人使用进度条与后台工作者和计时器。
但我不明白我应该在哪里使用我的解决方案。在后台工作者DoWork()
事件中?我不想通过滥用进度条来伪造它,例如设置progressBar.Maximum = 100,progressBar.Value = 0并且只要计时器正在滴答将值增加5.进度条必须报告实际进度而程序正在运行。
以下是我现在用来导入数据的解决方案:
private void btnImport_Click(object sender, EventArgs e)
{
if (lsbxBrowsedFiles.Items.Count != 0)
{
ArrayList salesHeaderArr = new ArrayList();
ArrayList salesDetailArr = new ArrayList();
int i = 0;
while (i < browsedXmlFileList.Count)
{
if (browsedXmlFileList[i].ToUpper().EndsWith("SALESHEADER.XML"))
{
salesHeaderArr.Add(browsedXmlFileList[i]);
}
if (browsedXmlFileList[i].ToUpper().EndsWith("SALESDETAIL.XML"))
{
salesDetailArr.Add(browsedXmlFileList[i]);
}
i++;
}
if (selectedFileIsNotInDestinationFolder(salesHeaderArr, salesDetailArr) == true)
{
i = 0;
while (i < salesHeaderArr.Count)
{
SalesHeader salesHeader = new SalesHeader();
string sourceFilePath = salesHeaderArr[i].ToString();
readXMLFiles(sourceFilePath, SALES_HEADER);
SalesHeader salesCheck = (SalesHeader)salesHeaderList[0];
string checkOutletCode = salesCheck.OutletCode;
DateTime checkBusDate = salesCheck.BusinessDate.Value;
if (SalesHeader.IsThisRowAlreadyImportedInSalesHeader(checkOutletCode, checkBusDate) == false)
{
salesHeader.ImportSalesHeader(salesHeaderList);
salesHeader.CreateImportDataLog(getDestinationFilePath(sourceFilePath),
DateTime.Now, salesHeaderList.Count, SALES_HEADER);
}
else
{
string errorDate = checkBusDate.ToString("dd MMMM, yyyy");
MessageBox.Show("Selected XML File with BusinessDate: " + errorDate + " has been already imported.",
"ABC Cafe Import Sales Wizard");
MessageBox.Show("Please select a file which has not been imported!",
"ABC Cafe Import Sales Wizard");
return;
}
MoveXMLFiletoDestinationFolder(sourceFilePath);
i++;
}
i = 0;
while (i < salesDetailArr.Count)
{
SalesDetail salesDetail = new SalesDetail();
string sourceFilePath = salesDetailArr[i].ToString();
readXMLFiles(sourceFilePath, SALES_DETAIL);
SalesDetail salesCheck = (SalesDetail)salesDetailList[0];
string checkOutletCode = salesCheck.OutletCode;
DateTime checkBusDate = salesCheck.BusinessDate.Value;
if (SalesDetail.IsThisRowAlreadyImportedInSalesDetail(checkOutletCode, checkBusDate) == false)
{
salesDetail.ImportSalesDetail(salesDetailList);
salesDetail.GenerateCarryForward(salesDetailList);
salesDetail.CalculateImportInventoryBalance(salesDetailList);
salesDetail.CreateImportDataLog(getDestinationFilePath(sourceFilePath), DateTime.Now, salesDetailList.Count, SALES_DETAIL);
}
else
{
string errorDate = checkBusDate.ToString("dd MMMM, yyyy");
MessageBox.Show("Selected XML File with BusinessDate: " + errorDate + " has been already imported.",
"ABC Cafe Import Sales Wizard");
MessageBox.Show("Please select a file which has not been imported!",
"ABC Cafe Import Sales Wizard");
return;
}
MoveXMLFiletoDestinationFolder(sourceFilePath);
i++;
}
MessageBox.Show("Import has been successfully completed!",
"ABC Cafe Import Sales Wizard");
clearListBoxItems();
lblMessage.Visible = false;
}
//Abort the import operation here!
else
{
MessageBox.Show("Please select a file which has not been imported!",
"ABC Cafe Import Sales Wizard");
clearListBoxItems();
lblMessage.Visible = false;
}
}
else
{
MessageBox.Show("Please select XML files to import!",
"ABC Cafe Import Sales Wizard");
}
}
非常感谢任何帮助!
答案 0 :(得分:3)
这就是我在我的应用程序中使用Progress Bar
的方法。
private void btnNext_Click(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.ProgressChanged += (se, eventArgs) => {
this.progressBar.Maximum = 100;
this.progressBar.Minimum = 0;
this.progressBar.Value = eventArgs.ProgressPercentage;
lblStatus.Text = eventArgs.UserState as String;
lblPercentage.Text = String.Format("Progress: {0} %", eventArgs.ProgressPercentage);
};
worker.DoWork += (se, eventArgs) => {
int progress = 0;
((BackgroundWorker)se).ReportProgress(progress, "Initializing the files...");
//Process that takes a long time
//Formula to calculate Progress Percentage
//This is how I calculated for my program. Divide 100 by number of loops you have
int findPercentage = ((i + 1) * 100) / salesHeaderArr.Count;
progress = 0;
progress += findPercentage / 2;
//Report back to the UI
string progressStatus = "Importing Sales Header... (" + getSourceFileName(sourceFilePath) + ")";
((BackgroundWorker)se).ReportProgress(progress, progressStatus);
//After Iterating through all the loops, update the progress to "Complete"
((BackgroundWorker)se).ReportProgress(100, "Complete...");
};
worker.RunWorkerCompleted += (se, eventArgs) =>
{
//Display smth or update status when progress is completed
lblStatus.Location = new Point(20, 60);
lblStatus.Text = "Your import has been completed. \n\nPlease Click 'Finish' button to close the wizard or \n'Back' button to go back to the previous page.";
lblPercentage.Visible = false;
progressBar.Visible = false;
btnBack.Enabled = true;
btnFinish.Enabled = true;
};
worker.RunWorkerAsync();
}
答案 1 :(得分:1)
你的程序有很多循环,因为在每次循环迭代中很难获得增量值并增加进度条值。你可以将进度条最大值设置为100,然后将100除以你拥有的循环次数说X。
所以诀窍就是在每个循环完成时用这个值填充进度条
是的,你应该把这段代码放在backgroundworker的DoWork()
中,否则它会冻结表格。也不需要计时器。
答案 2 :(得分:-1)
您可以在处理时使用ManualResetEvent,现在让Progressbar增加直到达到某一点并等待Set。
示例:
你有这2个字段
private int progress = 0;
private ManualResetEvent reset = new ManualResetEvent(false);
// Sets it to unsignalled
private ManualResetEvent reset2 = new ManualResetEvent(false);
while(progress < 40)
{
progress ++;
}
reset.WaitOne();
while(progress < 90)
{
progress ++;
}
reset2.WaitOne();
while(progress < 100)
{
progress ++;
}
//这完成了进度,现在你的实际工作,你必须发出那些等待的信号。
DoWork()
{
// long process here. . . .
reset.Set();
// Another long process
reset2.Set();
}