2013-09-24 68 views
2

我有我自己的解決方案,在我的Windows窗體應用程序中導入月度銷售數據。當用戶點擊import按鈕時,程序實際上正在運行,但看起來沒有響應。該過程需要大約5分鐘的時間。如何在Windows窗體C#中實現進度條?

所以,我想實現一個帶有狀態條標籤的進度條作爲用戶界面顯示,讓用戶知道完成了多少任務。這也是我第一次在我的程序中使用進度條。所以,我通讀了一些教程,介紹如何使用它。有些人使用進度條與後臺工作人員和計時器。

但我不明白我應該使用我擁有的解決方案。在後臺工作人員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

爲簡單起見,請考慮使用異步/等待結構。檢查這個[SO問題](http://stackoverflow.com/questions/17972268/async-await-with-a-winforms-progressbar) – ntr

+0

只需將進度條向下放置,在方法開始時將進度條設置爲「Maximum '屬性到您要迭代的文件數量,每次迭代文件時,都會爲進度條'Value'屬性添加一個文件。如果程序沒有響應或顯示進度,則每次迭代後都要使用一個'Application.DoEvents()'調用。 – Mitch

回答

1

你的程序有很多循環,因爲這將是很難獲得增值並增加在每個循環中的進度條值iteration.You進度條最大可設置爲100,然後由數除以100的循環使用,你有十

因此,關鍵是這個值填充進度條時,每個循環完成

,是的,你應該把在的BackgroundWorker的DoWork()這個代碼,否則將凍結form.Also不需要計時器。

+0

感謝您的解釋。你能舉一些例子來做這件事嗎?我有點困惑。在這種情況下只有2個循環。 SalesHeader&SalesDetail。在每個循環中,我使用'int percents =((i + 1)* 100)/ salesDetailArr.Count;'來獲取百分比和'backgroundWorker.ReportProgress(percents,i);'報告進度。但是,它不會回報到'backgroundWorker_ProgressChanged'方法,並且進度條增量保持爲0.在第二個循環內部,當程序執行ImportSalesDetail()方法時,它會增加到50.可以知道我做錯了什麼嗎? –

+0

你有沒有添加委託。我建議你刪除%的東西,繼續我建議的方法。雖然它可能不會顯示確切的進度,但它確實報告進度,並且不需要'backgroundWorker.ReportProgress' – techno

+1

我將您的答案標記爲正確答案。我用這個公式來查找進度百分比。 'int findPercentage =((i + 1)* 100)/ salesHeaderArr.Count;'由此得到進度百分比。 'progress = 0'我將進程重置爲0.'progress + = findPercentage/2;'我的程序中有2個循環。所以,我除以2.所以,如果第一個循環完成運行,我會得到50%。在另一個循環中。我使用相同的公式,但在這裏'progress + =(findPercentage/2)+ 50;'我從第一個循環中加入了50。現在在你的幫助下,我完成了我的實施。謝謝。 –

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

我是不是給了你一個例子?它在類上聲明,現在在你的後臺工作,運行while循環,達到一定的值後,使用manualresetevent等待,然後在你的實際進程設置它,如果你想進度條處理。 請閱讀並吸收>>,我剛剛給出了答案,你問我要做更多的工作嗎? – DevEstacion

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

你從哪裏得到'i'? – Si8

+0

@ SiKni8你可以在我的問題中找到它。 'i'被用作'SalesHeader'和'SalesDetail'循環中的迭代。我在解決方案中使用的公式以這種方式工作。如果您有2個循環,請將您的百分比除以2.第一次循環後,您將有50%的過程。在第二個循環中,使用相同的公式,但在第一個循環中添加50。 –

+0

Oooops沒有意識到你回答了你自己的問題。謝謝。 – Si8