【问题标题】:C# Backgroundworker ReportProgress() not executingC# Backgroundworker ReportProgress() 未执行
【发布时间】:2020-06-03 20:05:25
【问题描述】:

您好,我正在尝试填充进度条,但 ReportProgress 调用由于某种原因未执行。

这是我的代码

    //create status_Worker
    status_Worker = new BackgroundWorker();
    status_Worker.DoWork += new DoWorkEventHandler(Status_DoWork);
    status_Worker.ProgressChanged += new ProgressChangedEventHandler(Worker_ProgressChanged);
    status_Worker.WorkerReportsProgress = true;
    status_Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);

    private void Status_DoWork(object sender, DoWorkEventArgs e)
    {
        //make call to Logger class getStatus method
        _logger.getStatus(sender);
    }

    private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressbar1.Value = e.ProgressPercentage;
    }

    private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
            return;
        } 
        else
        {
            Start_button.IsEnabled = true;
        }

    }

    private void Start_button_Click(object sender, RoutedEventArgs e)
    {
        //initiate status_Worker when button is clicked
        status_Worker.RunWorkerAsync();
        Start_button.IsEnabled = false;
    }

现在在 Logger 类中,我有了 getStatus() 方法。我调用本地服务器以获取已处理文件的状态以及所有工作的状态,我看到值已在我的 MainWindow.Status 上自动更新。

    public async Task getStatus(object sender)
    {
        BackgroundWorker statusWorker = (BackgroundWorker)sender;
        //Making a call to ReportProgress here works and it shows the progress bar
        //statusWorker.ReportProgress(99);

        //REQUEST STATUS from a server
        //Status format
        //CurrentParser, NumberOfFilesToParse,CountOfCompletedFiles,Status, NumberOfProcessRunning
        int CountOfCompletedFiles;
        int NumberOfFilesToParse;
        int percent;
        string status = "Running";
        string[] stats;
        char[] delimiterChars = { ' ', ',', '.', ':', '\t' };

        while(status!="Complete")
        {

            var getstatus = await request.GetStringAsync("http://localhost:8085/status");
            logs.Add(getstatus);
            stats = getstatus.Split(delimiterChars);
            NumberOfFilesToParse = Int32.Parse(stats[1]);
            CountOfCompletedFiles = Int32.Parse(stats[2]);
            status = stats[3];

            Thread.Sleep(1000);
            MainWindow.main.Status = "Files to process: " + NumberOfFilesToParse + " Files completed: " + CountOfCompletedFiles + " Status: " + status;

            if(NumberOfFilesToParse!=0 && status!="Complete")
            {
                percent = (CountOfCompletedFiles * 100) / NumberOfFilesToParse;
                //a call to ReportProgress here stalls the program at this point
                //statusWorker.ReportProgress(percent);
            }

        }
        MainWindow.main.Status = "Completed!";

    }

在 getStatus 方法开始时调用 ReportProgress 有效,但在我的 while 循环期间或之后调用 ReportProgress 会导致进程在该点停止。即使使用静态数字 ReportProgress(99),它也只会在开头执行

【问题讨论】:

  • 你在另一个线程上。还调用Thread.Sleep 会破坏异步操作的目的并且会停止。您根本不应该传入后台工作人员。

标签: c# progress-bar backgroundworker reportprogress


【解决方案1】:

您的Status_DoWork 方法正在执行即发即弃。它调用async Task 方法,然后忽略它返回的Task

您遇到的一个问题是BackgroundWorker simply doesn't work with async。实际情况是,一旦在getStatus 中到达第一个await,它就会从returns an incomplete TaskStatus_DoWork,然后退出。这会导致 BackgroundWorker 完成,因此引发进度事件对于 BackgroundWorker 不再有意义。

The modern replacement for BackgroundWorker is Task.Run,其中includes support for progress reporting。理想情况下,您只会use Task.Run for CPU-bound methods, not the I/O-bound methods

private void Start_button_Click(object sender, RoutedEventArgs e)
{
  Start_button.IsEnabled = false;
  var progress = new Progress<int>(update => progressbar1.Value = update);
  try
  {
    await _logger.getStatus(progress);
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message);
  }
  finally
  {
    Start_button.IsEnabled = true;
  }
}

public async Task getStatus(IProgress<int> progress)
{
  int CountOfCompletedFiles;
  int NumberOfFilesToParse;
  int percent;
  string status = "Running";
  string[] stats;
  char[] delimiterChars = { ' ', ',', '.', ':', '\t' };

  while(status!="Complete")
  {
    var getstatus = await request.GetStringAsync("http://localhost:8085/status");
    logs.Add(getstatus);
    stats = getstatus.Split(delimiterChars);
    NumberOfFilesToParse = Int32.Parse(stats[1]);
    CountOfCompletedFiles = Int32.Parse(stats[2]);
    status = stats[3];

    await Task.Run(() => Thread.Sleep(1000)); // process file in Task.Run
    MainWindow.main.Status = "Files to process: " + NumberOfFilesToParse + " Files completed: " + CountOfCompletedFiles + " Status: " + status;

    if(NumberOfFilesToParse!=0 && status!="Complete")
    {
      percent = (CountOfCompletedFiles * 100) / NumberOfFilesToParse;
      progress.Report(percent);
    }
  }
  MainWindow.main.Status = "Completed!";
}

【讨论】:

  • 谢谢!这行得通。只有我必须在 main 中创建一个名为“public async Task startStatus()”的新方法,因为“await _logger.getStatus(progress)”需要一个异步方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多