簡體   English   中英

如何將事件添加到具有較長處理步驟的 C# windows 應用程序

[英]How to add events to C# windows application with long processing step

我有一個 Windows 窗體應用程序,它的主要任務是讀取大文本文件中的每一行,然后在該行上執行一些搜索和替換后將該行寫入另一個文件。 由於文件非常大,超過 20 GB,該過程預計需要很長時間才能完成。

讀取、修改、寫入大文本文件的每一行的過程都會很耗時,所以我想在此過程中通知用戶應用程序的進度。 無非是計算文件中的行數,然后將當前行數除以完成工作的百分比。

我知道這是事件和委托的用武之地,但我不得不承認,即使在閱讀了許多關於如何使用這種模式的文章之后,我仍然感到困惑。 向我展示如何向此應用程序添加事件的任何幫助都會有所幫助。

下面是我正在嘗試做的一個例子。 必須用文件中的x替換t所有值。

WinForm 類

namespace ParseFileTool
{
    public partial class FormMain : Form
    {
      public FormMain()
      {
          InitializeComponent();
      }

      private void btnStartProcessing_Click(object sender, EventArgs e)
      {
        ProcessFile pf = new ProcessFile();
        pf.InputFilePath = "PATH TO INPUT FILE";
        pf.OutputFilePath = "PATH TO OUTPUT FILE";
        pf.StartProcessing();
      }
    }
}

文件處理器類

class ProcessFile
{
    public string InputFilePath { get; set; }
    public string OutputFilePath { get; set; }

    public void StartProcessing()
    {
      using (StreamReader sr = new StreamReader(this.InputFilePath))
      {
        string line;
        while ((line = sr.ReadLine()) != null)
        {
          string newLine = line.Replace("t","x");
          using (FileStream fs = new FileStream(this.OutputFilePath, FileMode.Append, FileAccess.Write))
          using (StreamWriter sw = new StreamWriter(fs))
          {
            sw.WriteLine(newLine);
          }    
        }
      }
    }
}

我還想知道是否應該在單獨的線程上啟動ProcessFile類的實例,以允許 GUI 正確更新,或者這不是必需的,因為要使用事件。

感謝您的幫助。 我肯定希望對事件感到滿意並訂閱它們。 我了解什么是委托,但我仍然不確定在哪里聲明它(winform 類或ProcessFile類)以及如何處理傳遞回事件處理程序的數據(如處理的行號)。

我喜歡WinFormsBackgroundWorker ,盡管您也可以研究更新的async/await模型。

BackgroundWorker拖放到FormMain表單上並設置ReportsProgress = true 訂閱可用事件,用於工作和報告進度。

將任何不接觸 UI 的內容移動到DoWork事件中,該事件在單獨的線程上運行。 修改您的循環,使其定期報告進度。

public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
  var inputFilePath = "input file path";
  var outputFilePath = "output file Path";

  using (var sr = new StreamReader(inputFilePath))
  {
    int counter = 0;

    string line;
    while ((line = sr.ReadLine()) != null)
    {
      // do all the important stuff

      counter++;

      // report progress after every 100 lines
      // reporting too often can essentially lock the UI by continuously updating it
      if (counter % 100 == 0)
        backgroundWorker1.ReportProgress(counter);
    }
  }
}

ProgressChanged事件在 UI 線程上運行,因此您可以接受傳遞給它的任何DoWork事件並將其顯示給用戶。

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
  lblProgress.Text = string.Format("Processed {0} lines.", e.ProgressPercentage);
}

您可能也想訂閱RunWorkerCompleted事件...

void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  lblProgress.Text = "Job finished!";
}

通過調用啟動它:

backgroundWorker1.RunWorkerAsync();

您需要使用后台線程。 這里有很多選項,但最簡單的是:

Task.Run(() => pf.StartProcessing());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM