在哪里放置 BackgroundWorker

Where to place the BackgroundWorker

我有一个 class 收集有关机器的信息(这是一个示例 - 总共 GetInfo() 可能需要几分钟才能 运行):

public class Scanner
{
    public void GetInfo()
    {
        this.Name = GetName();
        this.OS = GetOS();
    }

    public string Name { get; set; }
    public string OS { get; set; }
    public string Status { get; set; }

    private string GetName() { this.Status = "Getting computer name"; /*More operations*/ }
    private string GetOS() { this.Status = "Getting OS"; /*More operations*/ }
}

这是由需要向用户提供状态反馈的表单调用的。

TextBox1.Text = scanner.Status;

我的问题是,要实现这一点,实现线程以使应用程序保持响应的最佳方式是什么?

我在表单中有一个 BackgroundWorker 运行ning 并调用 GetName()、GetOS() 等本身并且工作正常,但代码不是很可重复 - 我想要保持低维护在 class 中保留 GetInfo() 方法,因此如果我需要 运行 从其他地方进行扫描,那么只有一段代码知道如何进行。

我可以将 BackgroundWorker 移动到 GetInfo(),但是表单如何能够在不执行循环和锁定 UI 的情况下检查状态 属性?

也许有一个 BackgroundWorker 形式为 运行 GetInfo(),然后 运行 另一个 Worker 将检查状态并在检测到更改时更新表单?

这是我对线程处理的第一次正确尝试,我无法理解我认为这是一项相当常见的任务,因此我们将不胜感激。

注意:我也很乐意接受有关其他实现 Status 的方法的建议 属性 - 希望您明白我正在努力实现的目标。

/编辑:一些说明。

Scanner.GetInfo() 将被手动调用,例如在单击表单按钮时。 GetInfo() 然后会在收集信息时开始填充对象属性,可能需要 5 分钟才能完成。

我需要能够让用户了解其最新状态,而我能想到的唯一方法(以我目前的知识)是让 GetInfo() 更新 'Scanner.Status' 属性,然后表单可以在 interval/within 循环检查并在它更改时更新 UI。

如何使用 INotifyPropertyChanged 和 class 中的线程,如下所示:

public class Scanner : INotifyPropertyChanged
{
  private string _Name, _OS;
  public event PropertyChangedEventHandler PropertyChanged;

  public string Name
  {
    get
    {
      return _Name;
    }
    set
    {
      if (value != _Name)
      {
        _Name = value;
        NotifyPropertyChanged("Name");
      }
    }
  }

  public string OS
  {
    get
    {
      return _OS;
    }
    set
    {
      if (value != _OS)
      {
        _OS = value;
        NotifyPropertyChanged("OS");
      }
    }
  }

  public void GetInfo()
  {
    _Name = string.Empty;
    _OS = string.Empty;

    new Thread(() => this.Name = GetName()).Start();
    new Thread(() => this.OS = GetOS()).Start();
  }

  private void NotifyPropertyChanged(string pName)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged(this, new PropertyChangedEventArgs(pName));
    }
  }

  private string GetName() 
  { 
    return "long name operation here"; 
  }

  private string GetOS()
  {
    return "long OS operation here";
  }
}

然后在您的表单中,您可以使用以下内容:

Scanner m_Scanner = new Scanner();

public void Main()
{
  m_Scanner.PropertyChanged += UpdateGUI;
  m_Scanner.GetInfo();
}

private void UpdateGUI(object sender, PropertyChangedEventArgs e)
{
  if (e.PropertyName == "OS")
    txtOs.Text = m_Scanner.OS;
  else if (e.PropertyName == "Name")
    txtName.Text = m_Scanner.Name;
}