将后台工作者更新为异步等待 [英] Updating background worker to async-await

查看:94
本文介绍了将后台工作者更新为异步等待的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,这是我当前使用后台工作程序将大量内容保存到文件中的方式,同时向用户显示进度条,并防止在保存过程中对UI进行任何更改.我想我已经掌握了基本功能.模态ProgressWindow显示进度条,仅显示其他内容.如果必须的话,如何将其更改为async-await模式?

So this is how I currently use background worker to save a lot of stuff to file while presenting the user with a progress bar and preventing any changes to the UI while saving is in progress. I think I've captured the essential features. The modal ProgressWindow displays a progress bar and not much else. How would I go about changing this to async-await pattern, if I had to?

private ProgressForm ProgressWindow { get; set; }

/// <summary>On clicking save button, save stuff to file</summary>
void SaveButtonClick(object sender, EventArgs e)
{
  if (SaveFileDialog.ShowDialog() == DialogResult.OK)
  {
    if (!BackgroundWorker.IsBusy)
    {
      BackgroundWorker.RunWorkerAsync(SaveFileDialog.FileName);
      ProgressWindow= new ProgressForm();
      ProgressWindow.SetPercentageDone(0);
      ProgressWindow.ShowDialog(this);
    }
  }
}

/// <summary>Background worker task to save stuff to file</summary>
void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
  string path= e.Argument as string;

  // open file

  for (int i=0; i < 100; i++)
  {
    // get some stuff from UI
    // save stuff to file
    BackgroundWorker.ReportProgress(i);
  }

  // close file
}

/// <summary>On background worker progress, report progress</summary>
void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
  ProgressWindow.SetPercentageDone(e.ProgressPercentage);
}

/// <summary>On background worker finished, close progress form</summary>
void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  ProgressWindow.Close();
}

推荐答案

我有博客系列,对此进行了详细介绍.

I have a blog series that covers this in detail.

简而言之,用Task.Run代替BackgroundWorker,用IProgress<T>代替ReportProgress(和朋友).

In short, BackgroundWorker is replaced by Task.Run, and ReportProgress (and friends) is replaced by IProgress<T>.

因此,简单的翻译应如下所示:

So, a straightforward translation would look like this:

async void SaveButtonClick(object sender, EventArgs e)
{
  if (SaveFileDialog.ShowDialog() == DialogResult.OK)
  {
    ProgressWindow = new ProgressForm();
    ProgressWindow.SetPercentageDone(0);
    var progress = new Progress<int>(ProgressWindow.SetPercentageDone);
    var task = SaveAndClose(SaveFileDialog.FileName, progress));
    ProgressWindow.ShowDialog(this);
    await task;
  }
}

async Task SaveAndClose(string path, IProgress<int> progress)
{
  await Task.Run(() => Save(path, progress));
  ProgressWindow.Close();
}

void Save(string path, IProgress<int> progress)
{
  // open file

  for (int i=0; i < 100; i++)
  {
    // get some stuff from UI
    // save stuff to file
    if (progress != null)
      progress.Report(i);
  }

  // close file
}

改进说明:

  • 让后台线程进入UI(// get some stuff from UI)通常不是一个好主意.如果您可以在调用Task.Run之前从UI 收集所有信息并将其传递到Save方法中,则可能会更好.
  • It's not usually a good idea to have background threads reaching into the UI (// get some stuff from UI). It would probably work better if you could collect all the information from the UI before calling Task.Run and just pass it into the Save method.

这篇关于将后台工作者更新为异步等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆