我有一个收集有关机器信息的类(这是一个例子 - 总共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。
答案 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;
}