C# 在哪里放置后台工作人员
我有一个类可以收集有关机器的信息(这是一个示例-总的来说,GetInfo()可能需要几分钟才能运行): 这由需要向用户提供状态反馈的表单调用C# 在哪里放置后台工作人员,c#,backgroundworker,C#,Backgroundworker,我有一个类可以收集有关机器的信息(这是一个示例-总的来说,GetInfo()可能需要几分钟才能运行): 这由需要向用户提供状态反馈的表单调用 TextBox1.Text = scanner.Status; 我的问题是,要实现这一点,实现线程的最佳方法是什么,以使应用程序保持响应 我有一个BackgroundWorker运行在表单中,调用GetName()、GetOS()等,这很好,但是代码不是很容易重复-为了保持低维护,我想在类中保留一个GetInfo()方法,因此如果我需要从其他地方运行扫描
TextBox1.Text = scanner.Status;
我的问题是,要实现这一点,实现线程的最佳方法是什么,以使应用程序保持响应
我有一个BackgroundWorker运行在表单中,调用GetName()、GetOS()等,这很好,但是代码不是很容易重复-为了保持低维护,我想在类中保留一个GetInfo()方法,因此如果我需要从其他地方运行扫描,只有一段代码知道如何执行
我可以将BackgroundWorker移到GetInfo(),但是表单如何能够在不执行循环和锁定UI的情况下检查Status属性呢
也许让后台工作人员在表单中运行GetInfo(),然后运行另一个工作人员,该工作人员将检查状态并在检测到更改时更新表单
这是我第一次正确地使用线程,我想这是一项相当常见的任务,所以我无法理解这一点,因此,如果有任何帮助,我将不胜感激
注意:我也很乐意接受关于实现Status属性的其他方法的建议——希望你能得到我想要实现的东西
/编辑:一些澄清
将手动调用Scanner.GetInfo(),例如在表单按钮上单击。然后,GetInfo()将在收集信息时开始填充对象属性,可能需要5分钟才能完成
我需要能够让用户保持其状态的最新状态,我能想到的唯一方法(以我目前的知识)是让GetInfo()更新“Scanner.status”属性,表单可以在循环中每隔一段时间检查一次,并在更改时更新UI。如何使用
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;
}
没有。使用
async/await
和任务。改为运行。使用wait Task.Delay()编写循环是很简单的;var scanner=wait Task.Run(MyPollingFunction);textBox1.Text=scanner.Status代码>在它的主体中,或者创建一个带有异步
回调的计时器。是什么触发了GetInfo
的调用?或者你希望它什么时候发生?以一定的间隔循环?或者你手动触发它?这是在WPF/MVVM环境中使用的吗?看看Stephen C的博客:如果你想循环触发它,可能只是一个计时器就可以解决你的问题鉴于上面的回答,这就是我要做的。我无法访问txtName(在您的示例中),因为它是一个跨线程操作,但我将看看我能想出什么解决方法。在这里查看有关跨线程异常的信息:
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;
}