放置BackgroundWorker的位置

时间:2017-11-14 10:24:41

标签: c# backgroundworker

我有一个收集有关机器信息的类(这是一个例子 - 总共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并调用GetName(),GetOS()等本身并且工作正常,但代码不是很可重复 - 为了保持低维护我想保留一个GetInfo(在类中的方法,所以如果我需要从其他地方运行扫描,那么只有一段代码知道如何。

我可以将BackgroundWorker移动到GetInfo(),但是如何在不进行循环并锁定UI的情况下如何检查Status属性?

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

这是我第一次正确选择线程,并且不能理解我认为是一项相当普遍的任务,所以任何帮助都会受到赞赏。

注意:我也很乐意接受有关实施Status属性的其他方法的建议 - 希望您能得到我想要实现的目标。

/ edit:一些澄清。

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

我需要能够让用户了解其状态,并且我能想到这一点的唯一方法(使用我目前的知识)是GetInfo()更新' Scanner.Status& #39;属性,然后表单可以在一个循环中以间隔/内部进行检查,并在更改时更新UI。

1 个答案:

答案 0 :(得分:1)

如何使用INotifyPropertyChanged与类中的线程如下:

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;
}