我创建了一个GUI(winforms)并添加了一个后台工作程序以在一个单独的线程中运行。 后台工作人员需要不断更新2个标签。 backgroundworker线程应该以button1单击开始并永远运行。
class EcuData
{
public int RPM { get; set; }
public int MAP { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
EcuData data = new EcuData
{
RPM = 0,
MAP = 0
};
BackWorker1.RunWorkerAsync(data);
}
private void BackWorker1_DoWork(object sender, DoWorkEventArgs e)
{
EcuData argumentData = e.Argument as EcuData;
int x = 0;
while (x<=10)
{
//
// Code for reading in data from hardware.
//
argumentData.RPM = x; //x is for testing only!
argumentData.MAP = x * 2; //x is for testing only!
e.Result = argumentData;
Thread.Sleep(100);
x++;
}
private void BackWorker1_RunWorkerCompleted_1(object sender, RunWorkerCompletedEventArgs e)
{
EcuData data = e.Result as EcuData;
label1.Text = data.RPM.ToString();
label2.Text = data.MAP.ToString();
}
}
上面的代码刚刚在后台工作完成他的工作时更新了GUI,而这不是我正在寻找的。 p>
答案 0 :(得分:9)
您需要查看BackgroundWorker.ReportProgess。
您可以使用它定期将对象传回主线程中的方法,该方法可以为您更新标签。
答案 1 :(得分:3)
您可以使用System.Threading.Timer并通过调用主窗体上的BeginInvoke从Timer的回调方法更新UI。
uiUpdateTimer = new System.Threading.Timer(new TimerCallback(
UpdateUI), null, 200, 200);
private void UpdateUI(object state)
{
this.BeginInvoke(new MethodInvoker(UpdateUI));
}
private void UpdateUI()
{
// modify labels here
}
答案 2 :(得分:1)
class EcuData
{
public int RPM { get; set; }
public int MAP { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
EcuData data = new EcuData
{
RPM = 0,
MAP = 0
};
BackWorker1.RunWorkerAsync(data);
}
private void BackWorker1_DoWork(object sender, DoWorkEventArgs e)
{
EcuData argumentData = e.Argument as EcuData;
int x = 0;
while (x<=10)
{
e.Result = argumentData;
Thread.Sleep(100);
this.Invoke((MethodInvoker)delegate
{
label1.Text = Convert.ToString(argumentData.RPM = x); //send hardware data later instead, x is for testing only!
label2.Text = Convert.ToString(argumentData.MAP = x * 2); //send hardware data later instead, x is for testing only!
});
x++;
}
}
这有效,但这是正确的做法吗?