代码之家  ›  专栏  ›  技术社区  ›  danabnormal

BackgroundWorker的位置

  •  0
  • danabnormal  · 技术社区  · 7 年前

    我有一个收集机器信息的类(这是一个示例-总的来说,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移到GetInfo(),但是表单如何能够在不执行循环和锁定UI的情况下检查Status属性呢?

    也许让后台工作人员在表单中运行GetInfo(),然后运行另一个工作人员,该工作人员将检查状态并在检测到更改时更新表单?

    这是我第一次正确地使用线程,我想这是一项相当常见的任务,如果有任何帮助,我将不胜感激。

    /编辑:一些澄清。

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

    我需要能够让用户了解其最新状态,我能想到的唯一方法(根据我目前的知识)是让GetInfo()更新“扫描仪”。属性,然后表单可以每隔一段时间/在循环内检查该属性,并在其更改时更新UI。

    1 回复  |  直到 7 年前
        1
  •  1
  •   RooiWillie    7 年前

    使用如何 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;
    }